bitkeeper revision 1.616 (3fbca451cCh4CiAzcPFCijGwNS4Bjg)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 20 Nov 2003 11:24:01 +0000 (11:24 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 20 Nov 2003 11:24:01 +0000 (11:24 +0000)
Many files:
  Mods to new xclib.
Makefile:
  new file
  Rename: tools/xc/Makefile -> tools/xc/lib/Makefile
rpm.spec:
  Rename: tools/xc/rpm.spec -> tools/xc/lib/rpm.spec
xc.h:
  Rename: tools/xc/xc.h -> tools/xc/lib/xc.h
libxc_private.h:
  Rename: tools/xc/libxc_private.h -> tools/xc/lib/libxc_private.h
libxc_vif.c:
  Rename: tools/xc/libxc_vif.c -> tools/xc/lib/libxc_vif.c
libxc_vbd.c:
  Rename: tools/xc/libxc_vbd.c -> tools/xc/lib/libxc_vbd.c
libxc_private.c:
  Rename: tools/xc/libxc_private.c -> tools/xc/lib/libxc_private.c
libxc_misc.c:
  Rename: tools/xc/libxc_misc.c -> tools/xc/lib/libxc_misc.c
libxc_linux_save.c:
  Rename: tools/xc/libxc_linux_save.c -> tools/xc/lib/libxc_linux_save.c
libxc_linux_restore.c:
  Rename: tools/xc/libxc_linux_restore.c -> tools/xc/lib/libxc_linux_restore.c
libxc_linux_build.c:
  Rename: tools/xc/libxc_linux_build.c -> tools/xc/lib/libxc_linux_build.c
libxc_domain.c:
  Rename: tools/xc/libxc_domain.c -> tools/xc/lib/libxc_domain.c
libxc_bvtsched.c:
  Rename: tools/xc/libxc_bvtsched.c -> tools/xc/lib/libxc_bvtsched.c
Many files:
  mvdir

29 files changed:
.rootkeys
tools/Makefile
tools/libxc/Makefile [deleted file]
tools/libxc/libxc_bvtsched.c [deleted file]
tools/libxc/libxc_domain.c [deleted file]
tools/libxc/libxc_linux_build.c [deleted file]
tools/libxc/libxc_linux_restore.c [deleted file]
tools/libxc/libxc_linux_save.c [deleted file]
tools/libxc/libxc_misc.c [deleted file]
tools/libxc/libxc_private.c [deleted file]
tools/libxc/libxc_private.h [deleted file]
tools/libxc/libxc_vbd.c [deleted file]
tools/libxc/libxc_vif.c [deleted file]
tools/libxc/rpm.spec [deleted file]
tools/libxc/xc.h [deleted file]
tools/xc/Makefile [new file with mode: 0644]
tools/xc/lib/Makefile [new file with mode: 0644]
tools/xc/lib/libxc_bvtsched.c [new file with mode: 0644]
tools/xc/lib/libxc_domain.c [new file with mode: 0644]
tools/xc/lib/libxc_linux_build.c [new file with mode: 0644]
tools/xc/lib/libxc_linux_restore.c [new file with mode: 0644]
tools/xc/lib/libxc_linux_save.c [new file with mode: 0644]
tools/xc/lib/libxc_misc.c [new file with mode: 0644]
tools/xc/lib/libxc_private.c [new file with mode: 0644]
tools/xc/lib/libxc_private.h [new file with mode: 0644]
tools/xc/lib/libxc_vbd.c [new file with mode: 0644]
tools/xc/lib/libxc_vif.c [new file with mode: 0644]
tools/xc/lib/rpm.spec [new file with mode: 0644]
tools/xc/lib/xc.h [new file with mode: 0644]

index bbdd90398def9ae5a848a7ef4a123a8d519df337..5cdfe639edb54c6fb6b21e76621d14e75ab4c583 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3fb01fd5B-UeibZkmSCOUZckNyNFYA tools/internal/xi_vbd_list.c
 3f86be322bd0h9jG3krZFOUgCDoxZg tools/internal/xi_vif_params.c
 3eb781fd7211MZsLxJSiuy7W4KnJXg tools/internal/xi_vifinit
-3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/libxc/Makefile
-3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/libxc/libxc_bvtsched.c
-3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/libxc/libxc_domain.c
-3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/libxc/libxc_linux_build.c
-3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/libxc/libxc_linux_restore.c
-3fbba6db7li3FJiABYtCmuGxOJxEGw tools/libxc/libxc_linux_save.c
-3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/libxc/libxc_misc.c
-3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/libxc/libxc_private.c
-3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/libxc/libxc_private.h
-3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/libxc/libxc_vbd.c
-3fbba6dc38q-ioRlwSR_quw4G3qUeQ tools/libxc/libxc_vif.c
-3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/libxc/rpm.spec
-3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/libxc/xc.h
 3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
 3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
 3f6dc140C8tAeBfroAF24VrmCS4v_w tools/misc/miniterm/README
 3f13d81e6Z6806ihYYUw8GVKNkYnuw tools/misc/xen_nat_enable.README
 3f1668d4F29Jsw0aC0bJEIkOBiagiQ tools/misc/xen_read_console.c
 3f87ba90EUVPQLVOlFG0sW89BCwouQ tools/misc/xen_refresh_dev.c
+3fbca441SjQr8vJwTQIgH1laysaWog tools/xc/Makefile
+3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/xc/lib/Makefile
+3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/xc/lib/libxc_bvtsched.c
+3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/xc/lib/libxc_domain.c
+3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/xc/lib/libxc_linux_build.c
+3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/xc/lib/libxc_linux_restore.c
+3fbba6db7li3FJiABYtCmuGxOJxEGw tools/xc/lib/libxc_linux_save.c
+3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/xc/lib/libxc_misc.c
+3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/xc/lib/libxc_private.c
+3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/xc/lib/libxc_private.h
+3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/xc/lib/libxc_vbd.c
+3fbba6dc38q-ioRlwSR_quw4G3qUeQ tools/xc/lib/libxc_vif.c
+3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/xc/lib/rpm.spec
+3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/xc/lib/xc.h
 3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
 3f841450eJvqAD1Dldc0_aOweGiglQ xen/GUEST_CHANGES
 3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile
index 2e46cf66e69c55d8d208687e033d2a8cfd2f3e33..42c579823b7edcc9114cbefe1dddd178f0ee3bd2 100644 (file)
@@ -21,20 +21,20 @@ all:
        $(MAKE) -C balloon
        $(MAKE) -C control
        $(MAKE) -C internal
-       $(MAKE) -C libxc
+       $(MAKE) -C xc
        $(MAKE) -C misc
 
 install: all
        $(MAKE) -C balloon install
        $(MAKE) -C control install
        $(MAKE) -C internal install
-       $(MAKE) -C libxc install
+       $(MAKE) -C xc install
        $(MAKE) -C misc install
 
 clean:
        $(MAKE) -C balloon clean
        $(MAKE) -C control clean
        $(MAKE) -C internal clean
-       $(MAKE) -C libxc clean
+       $(MAKE) -C xc clean
        $(MAKE) -C misc clean
 
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
deleted file mode 100644 (file)
index 7bc64e2..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-
-CC       = gcc
-CFLAGS   = -c -Wall -O3 
-CFLAGS  += -I../../xen/include -I../../xenolinux-sparse/include
-
-HDRS     = $(wildcard *.h)
-OBJS     = $(patsubst %.c,%.o,$(wildcard libxc_*.c))
-
-LIBS     = libxc.a libxc.so
-
-all: check-for-zlib $(LIBS)
-       ranlib libxc.a
-
-check-for-zlib:
-       @if [ ! -e /usr/include/zlib.h ]; then \
-       echo "***********************************************************"; \
-       echo "ERROR: install zlib header files (http://www.gzip.org/zlib)"; \
-       echo "***********************************************************"; \
-       false; \
-       fi
-
-install: all
-       mkdir -p ../../../install/lib
-       mkdir -p ../../../install/include
-       cp -a $(LIBS) ../../../install/lib
-       for i in $(LIBS) do ; chmod 755 ../../../install/bin/$i ; done
-       cp -a xc.h ../../../install/include
-       chmod 644 ../../../install/include/xc.h
-
-clean:
-       $(RM) *.a *.so *.o *.rpm $(LIBS)
-
-rpm: all
-       rm -rf staging
-       mkdir staging
-       mkdir staging/i386
-       rpmbuild --define "staging$$PWD/staging" --define '_builddir.' \
-               --define "_rpmdir$$PWD/staging" -bb rpm.spec
-       mv staging/i386/*.rpm .
-       rm -rf staging
-
-libxc.so: $(OBJS)
-       $(LD) -shared -o $@ $^ -lz
-
-libxc.a: libxc.a($(OBJS))
-
-%.o: %.c $(HDRS) Makefile
-       $(CC) $(CFLAGS) -o $@ $<
diff --git a/tools/libxc/libxc_bvtsched.c b/tools/libxc/libxc_bvtsched.c
deleted file mode 100644 (file)
index 5230e96..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/******************************************************************************
- * libxc_bvtsched.c
- * 
- * API for manipulating parameters of the Borrowed Virtual Time scheduler.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#include "libxc_private.h"
-
-int xc_bvtsched_global_set(unsigned long ctx_allow)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_BVTCTL;
-    op.u.bvtctl.ctx_allow = ctx_allow;
-    return do_dom0_op(&op);
-}
-
-int xc_bvtsched_domain_set(unsigned int domid,
-                           unsigned long mcuadv,
-                           unsigned long warp,
-                           unsigned long warpl,
-                           unsigned long warpu)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_ADJUSTDOM;
-    op.u.adjustdom.domain  = domid;
-    op.u.adjustdom.mcu_adv = mcuadv;
-    op.u.adjustdom.warp    = warp;
-    op.u.adjustdom.warpl   = warpl;
-    op.u.adjustdom.warpu   = warpu;
-    return do_dom0_op(&op);
-}
diff --git a/tools/libxc/libxc_domain.c b/tools/libxc/libxc_domain.c
deleted file mode 100644 (file)
index a6c2906..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/******************************************************************************
- * libxc_domain.c
- * 
- * API for manipulating and obtaining information on domains.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#include "libxc_private.h"
-
-int xc_domain_create(unsigned int mem_kb, const char *name)
-{
-    int err;
-    dom0_op_t op;
-
-    op.cmd = DOM0_CREATEDOMAIN;
-    op.u.createdomain.memory_kb = mem_kb;
-    strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
-    op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0';
-
-    err = do_dom0_op(&op);
-
-    return (err < 0) ? err : op.u.createdomain.domain;
-}    
-
-
-int xc_domain_start(unsigned int domid)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_STARTDOMAIN;
-    op.u.startdomain.domain = domid;
-    return do_dom0_op(&op);
-}    
-
-
-int xc_domain_stop(unsigned int domid)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_STOPDOMAIN;
-    op.u.stopdomain.domain = domid;
-    return do_dom0_op(&op);
-}    
-
-
-int xc_domain_destroy(unsigned int domid, int force)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_DESTROYDOMAIN;
-    op.u.destroydomain.domain = domid;
-    op.u.destroydomain.force  = !!force;
-    return do_dom0_op(&op);
-}
-
-int xc_domain_getinfo(unsigned int first_domid,
-                      unsigned int max_doms,
-                      xc_dominfo_t *info)
-{
-    unsigned int nr_doms, next_domid = first_domid;
-    dom0_op_t op;
-
-    for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
-    {
-        op.cmd = DOM0_GETDOMAININFO;
-        op.u.getdomaininfo.domain = next_domid;
-        if ( do_dom0_op(&op) < 0 )
-            break;
-        info->domid   = op.u.getdomaininfo.domain;
-        info->cpu     = op.u.getdomaininfo.processor;
-        info->has_cpu = op.u.getdomaininfo.has_cpu;
-        info->stopped = (op.u.getdomaininfo.state == DOMSTATE_STOPPED);
-        info->nr_pages = op.u.getdomaininfo.tot_pages;
-        info->cpu_time = op.u.getdomaininfo.cpu_time;
-        strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME);
-        info->name[XC_DOMINFO_MAXNAME-1] = '\0';
-
-        next_domid = op.u.getdomaininfo.domain + 1;
-    }
-
-    return nr_doms;
-}
diff --git a/tools/libxc/libxc_linux_build.c b/tools/libxc/libxc_linux_build.c
deleted file mode 100644 (file)
index a1e4227..0000000
+++ /dev/null
@@ -1,481 +0,0 @@
-/******************************************************************************
- * libxc_linux_build.c
- */
-
-#include "libxc_private.h"
-#include <zlib.h>
-
-/* This string is written to the head of every guest kernel image. */
-#define GUEST_SIG   "XenoGues"
-#define SIG_LEN    8
-
-#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
-#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-
-static long get_tot_pages(int domid)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_GETDOMAININFO;
-    op.u.getdomaininfo.domain = domid;
-    return (do_dom0_op(&op) < 0) ? -1 : op.u.getdomaininfo.tot_pages;
-}
-
-static int get_pfn_list(
-    int domid, unsigned long *pfn_buf, unsigned long max_pfns)
-{
-    dom0_op_t op;
-    int ret;
-    op.cmd = DOM0_GETMEMLIST;
-    op.u.getmemlist.domain   = domid;
-    op.u.getmemlist.max_pfns = max_pfns;
-    op.u.getmemlist.buffer   = pfn_buf;
-
-    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
-        return -1;
-
-    ret = do_dom0_op(&op);
-
-    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
-
-    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
-}
-
-static int send_pgupdates(mmu_update_t *updates, int nr_updates)
-{
-    int ret = -1;
-    privcmd_hypercall_t hypercall;
-
-    hypercall.op     = __HYPERVISOR_mmu_update;
-    hypercall.arg[0] = (unsigned long)updates;
-    hypercall.arg[1] = (unsigned long)nr_updates;
-
-    if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 )
-        goto out1;
-
-    if ( do_xen_hypercall(&hypercall) < 0 )
-        goto out2;
-
-    ret = 0;
-
- out2: (void)munlock(updates, nr_updates * sizeof(*updates));
- out1: return ret;
-}
-
-/* Read the kernel header, extracting the image size and load address. */
-static int read_kernel_header(gzFile gfd, long dom_size, 
-                              unsigned long *load_addr, int verbose)
-{
-    char signature[SIG_LEN];
-
-    gzread(gfd, signature, SIG_LEN);
-    if ( strncmp(signature, GUEST_SIG, SIG_LEN) )
-    {
-        if ( verbose )
-            ERROR("Kernel image does not contain required signature");
-        return -1;
-    }
-
-    /* Read the load address which immediately follows the Xeno signature. */
-    gzread(gfd, load_addr, sizeof(unsigned long));
-
-    return 0;
-}
-
-static int copy_to_domain_page(unsigned long dst_pfn, void *src_page)
-{
-    void *vaddr = map_pfn(dst_pfn);
-    if ( vaddr == NULL )
-        return -1;
-    memcpy(vaddr, src_page, PAGE_SIZE);
-    unmap_pfn(vaddr);
-    return 0;
-}
-
-static int setup_guestos(
-    int dom, gzFile kernel_gfd, int initrd_fd, unsigned long tot_pages,
-    unsigned long *virt_startinfo_addr, unsigned long virt_load_addr, 
-    dom0_builddomain_t *builddomain, const char *cmdline,
-    unsigned long shared_info_frame, int verbose)
-{
-    l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
-    l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
-    unsigned long *page_array = NULL;
-    mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL;
-    int alloc_index, num_pt_pages;
-    unsigned long l2tab;
-    unsigned long l1tab = 0;
-    unsigned long num_pgt_updates = 0;
-    unsigned long count, pt_start, i, j;
-    unsigned long initrd_addr = 0, initrd_len = 0;
-    start_info_t *start_info;
-    shared_info_t *shared_info;
-    unsigned long ksize;
-
-    memset(builddomain, 0, sizeof(*builddomain));
-
-    if ( init_pfn_mapper() < 0 )
-        goto error_out;
-
-    pgt_updates = malloc((tot_pages + 1024) * 3 * sizeof(mmu_update_t));
-    page_array = malloc(tot_pages * sizeof(unsigned long));
-    pgt_update_arr = pgt_updates;
-    if ( (pgt_update_arr == NULL) || (page_array == NULL) )
-    {
-        if ( verbose )
-            PERROR("Could not allocate memory");
-        goto error_out;
-    }
-
-    if ( get_pfn_list(dom, page_array, tot_pages) != tot_pages )
-    {
-        if ( verbose )
-            PERROR("Could not get the page frame list");
-        goto error_out;
-    }
-
-    /* Load the guest OS image. Let it take no more than 1/2 memory.*/
-    for ( i = 0; i < ((tot_pages/2)*PAGE_SIZE); i += PAGE_SIZE )
-    {
-        char page[PAGE_SIZE];
-        int size;
-        if ( (size = gzread(kernel_gfd, page, PAGE_SIZE)) == -1 )
-        {
-            if ( verbose )
-                PERROR("Error reading kernel image, could not"
-                       " read the whole image.");
-            goto error_out;
-        }
-        if ( size == 0 )
-            goto kernel_copied;
-        copy_to_domain_page(page_array[i>>PAGE_SHIFT], page);
-    }
-    if ( verbose )
-        ERROR("Kernel too big to safely fit in domain memory");
-    goto error_out;
-
- kernel_copied:
-    /* ksize is kernel-image size rounded up to a page boundary. */
-    ksize = i;
-
-    /* Load the initial ramdisk image. */
-    if ( initrd_fd >= 0 )
-    {
-        struct stat stat;
-        unsigned long isize;
-
-        if ( fstat(initrd_fd, &stat) < 0 )
-        {
-            if ( verbose )
-                PERROR("Could not stat the initrd image");
-            goto error_out;
-        }
-        isize = stat.st_size;
-        if ( (isize + ksize) > ((tot_pages/2) * PAGE_SIZE) )
-        {
-            if ( verbose )
-                ERROR("Kernel/initrd too big to safely fit in domain memory");
-            goto error_out;
-        }
-
-        initrd_addr = virt_load_addr + ksize;
-        initrd_len  = isize;
-
-        for ( j = 0, i = ksize; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
-        {
-            char page[PAGE_SIZE];
-            int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE;
-            if ( read(initrd_fd, page, size) != size )
-            {
-                if ( verbose )
-                    PERROR("Error reading initrd image, could not"
-                           " read the whole image.");
-                goto error_out;
-            } 
-            copy_to_domain_page(page_array[i>>PAGE_SHIFT], page);
-        }
-    }
-
-    alloc_index = tot_pages - 1;
-
-    /* Count bottom-level PTs, rounding up. */
-    num_pt_pages = (l1_table_offset(virt_load_addr) + tot_pages + 1023) / 1024;
-
-    /* We must also count the page directory. */
-    num_pt_pages++;
-
-    /* Index of first PT page. */
-    pt_start = tot_pages - num_pt_pages;
-
-    /*
-     * First allocate page for page dir. Allocation goes backwards from the end
-     * of the allocated physical address space.
-     */
-    l2tab = page_array[alloc_index] << PAGE_SHIFT;
-    alloc_index--;
-    builddomain->ctxt.pt_base = l2tab;
-
-    /*
-     * Pin down l2tab addr as page dir page - causes hypervisor to provide
-     * correct protection for the page
-     */ 
-    pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND;
-    pgt_updates->val = MMUEXT_PIN_L2_TABLE;
-    pgt_updates++;
-    num_pgt_updates++;
-
-    /* Initialise the page tables. */
-    if ( (vl2tab = map_pfn(l2tab >> PAGE_SHIFT)) == NULL )
-        goto error_out;
-    memset(vl2tab, 0, PAGE_SIZE);
-    vl2e = vl2tab + l2_table_offset(virt_load_addr);
-    for ( count = 0; count < tot_pages; count++ )
-    {    
-        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) 
-        {
-            l1tab = page_array[alloc_index] << PAGE_SHIFT;
-            if ( (vl1tab = map_pfn(l1tab >> PAGE_SHIFT)) == NULL )
-                goto error_out;
-            memset(vl1tab, 0, PAGE_SIZE);
-            alloc_index--;
-               
-            vl1e = vl1tab + l1_table_offset(virt_load_addr + 
-                                            (count << PAGE_SHIFT));
-
-            /* make apropriate entry in the page directory */
-            pgt_updates->ptr = (unsigned long)vl2e;
-            pgt_updates->val = l1tab | L2_PROT;
-            pgt_updates++;
-            num_pgt_updates++;
-            vl2e++;
-        }
-
-        if ( count < pt_start )
-        {
-            pgt_updates->ptr = (unsigned long)vl1e;
-            pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT;
-            pgt_updates++;
-            num_pgt_updates++;
-            vl1e++;
-        }
-        else
-        {
-            pgt_updates->ptr = (unsigned long)vl1e;
-            pgt_updates->val = 
-                ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
-            pgt_updates++;
-            num_pgt_updates++;
-            vl1e++;
-        }
-
-        pgt_updates->ptr = 
-            (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
-        pgt_updates->val = count;
-        pgt_updates++;
-        num_pgt_updates++;
-    }
-
-    *virt_startinfo_addr =
-        virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
-
-    start_info = map_pfn(page_array[alloc_index-1]);
-    memset(start_info, 0, sizeof(*start_info));
-    start_info->pt_base     = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
-    start_info->mod_start   = initrd_addr;
-    start_info->mod_len     = initrd_len;
-    start_info->nr_pages    = tot_pages;
-    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
-    start_info->dom_id      = dom;
-    start_info->flags       = 0;
-    strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN);
-    start_info->cmd_line[MAX_CMD_LEN-1] = '\0';
-
-    unmap_pfn(start_info);
-
-    /* shared_info page starts its life empty. */
-    shared_info = map_pfn(shared_info_frame);
-    memset(shared_info, 0, PAGE_SIZE);
-    unmap_pfn(shared_info);
-
-    /* Send the page update requests down to the hypervisor. */
-    if ( send_pgupdates(pgt_update_arr, num_pgt_updates) < 0 )
-        goto error_out;
-
-    free(page_array);
-    free(pgt_update_arr);
-    return 0;
-
- error_out:
-    if ( page_array == NULL )
-        free(page_array);
-    if ( pgt_update_arr == NULL )
-        free(pgt_update_arr);
-    return -1;
-}
-
-int xc_domain_build(unsigned int domid,
-                    const char *image_name,
-                    const char *ramdisk_name,
-                    const char *cmdline,
-                    int verbose)
-{
-    dom0_op_t launch_op, op;
-    unsigned long load_addr;
-    long tot_pages;
-    int kernel_fd, initrd_fd = -1;
-    gzFile kernel_gfd;
-    int rc, i;
-    full_execution_context_t *ctxt;
-    unsigned long virt_startinfo_addr;
-
-    if ( (tot_pages = get_tot_pages(domid)) < 0 )
-    {
-        if ( verbose )
-            PERROR("Could not find total pages for domain");
-        return 1;
-    }
-
-    kernel_fd = open(image_name, O_RDONLY);
-    if ( kernel_fd < 0 )
-    {
-        if ( verbose )
-            PERROR("Could not open kernel image");
-        return 1;
-    }
-
-    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
-    {
-        if ( verbose )
-            PERROR("Could not allocate decompression state for state file");
-        close(kernel_fd);
-        return 1;
-    }
-
-    rc = read_kernel_header(kernel_gfd,
-                            tot_pages << (PAGE_SHIFT - 10), 
-                            &load_addr, verbose);
-    if ( rc < 0 )
-        goto error_out;
-    
-    if ( (load_addr & (PAGE_SIZE-1)) != 0 )
-    {
-        if ( verbose )
-            ERROR("We can only deal with page-aligned load addresses");
-        goto error_out;
-    }
-
-    if ( (load_addr + (tot_pages << PAGE_SHIFT)) > HYPERVISOR_VIRT_START )
-    {
-        if ( verbose )
-            ERROR("Cannot map all domain memory without hitting Xen space");
-        goto error_out;
-    }
-
-    if ( ramdisk_name != NULL )
-    {
-        initrd_fd = open(ramdisk_name, O_RDONLY);
-        if ( initrd_fd < 0 )
-        {
-            if ( verbose )
-                PERROR("Could not open the initial ramdisk image");
-            goto error_out;
-        }
-    }
-
-    op.cmd = DOM0_GETDOMAININFO;
-    op.u.getdomaininfo.domain = domid;
-    if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) )
-    {
-        if ( verbose )
-            PERROR("Could not get info on domain");
-        goto error_out;
-    }
-    if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
-         (op.u.getdomaininfo.ctxt.pt_base != 0) )
-    {
-        if ( verbose )
-            ERROR("Domain is already constructed");
-        goto error_out;
-    }
-
-    if ( setup_guestos(domid, kernel_gfd, initrd_fd, tot_pages,
-                       &virt_startinfo_addr,
-                       load_addr, &launch_op.u.builddomain, cmdline,
-                       op.u.getdomaininfo.shared_info_frame, verbose) < 0 )
-    {
-        if ( verbose )
-            ERROR("Error constructing guest OS");
-        goto error_out;
-    }
-
-    if ( initrd_fd >= 0 )
-        close(initrd_fd);
-    gzclose(kernel_gfd);
-
-    ctxt = &launch_op.u.builddomain.ctxt;
-
-    ctxt->flags = 0;
-
-    /*
-     * Initial register values:
-     *  DS,ES,FS,GS = FLAT_RING1_DS
-     *       CS:EIP = FLAT_RING1_CS:start_pc
-     *       SS:ESP = FLAT_RING1_DS:start_stack
-     *          ESI = start_info
-     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
-     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
-     */
-    ctxt->i386_ctxt.ds = FLAT_RING1_DS;
-    ctxt->i386_ctxt.es = FLAT_RING1_DS;
-    ctxt->i386_ctxt.fs = FLAT_RING1_DS;
-    ctxt->i386_ctxt.gs = FLAT_RING1_DS;
-    ctxt->i386_ctxt.ss = FLAT_RING1_DS;
-    ctxt->i386_ctxt.cs = FLAT_RING1_CS;
-    ctxt->i386_ctxt.eip = load_addr;
-    ctxt->i386_ctxt.esp = virt_startinfo_addr;
-    ctxt->i386_ctxt.esi = virt_startinfo_addr;
-    ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
-
-    /* FPU is set up to default initial state. */
-    memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
-
-    /* Virtual IDT is empty at start-of-day. */
-    for ( i = 0; i < 256; i++ )
-    {
-        ctxt->trap_ctxt[i].vector = i;
-        ctxt->trap_ctxt[i].cs     = FLAT_RING1_CS;
-    }
-    ctxt->fast_trap_idx = 0;
-
-    /* No LDT. */
-    ctxt->ldt_ents = 0;
-    
-    /* Use the default Xen-provided GDT. */
-    ctxt->gdt_ents = 0;
-
-    /* Ring 1 stack is the initial stack. */
-    ctxt->ring1_ss  = FLAT_RING1_DS;
-    ctxt->ring1_esp = virt_startinfo_addr;
-
-    /* No debugging. */
-    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
-
-    /* No callback handlers. */
-    ctxt->event_callback_cs     = FLAT_RING1_CS;
-    ctxt->event_callback_eip    = 0;
-    ctxt->failsafe_callback_cs  = FLAT_RING1_CS;
-    ctxt->failsafe_callback_eip = 0;
-
-    launch_op.u.builddomain.domain   = domid;
-    launch_op.u.builddomain.num_vifs = 1;
-
-    launch_op.cmd = DOM0_BUILDDOMAIN;
-    rc = do_dom0_op(&launch_op);
-    
-    return rc;
-
- error_out:
-    if ( initrd_fd >= 0 )
-        close(initrd_fd);
-    gzclose(kernel_gfd);
-    return -1;
-}
diff --git a/tools/libxc/libxc_linux_restore.c b/tools/libxc/libxc_linux_restore.c
deleted file mode 100644 (file)
index 6afa2e2..0000000
+++ /dev/null
@@ -1,476 +0,0 @@
-/******************************************************************************
- * libxc_linux_restore.c
- * 
- * Restore the state of a Xenolinux session.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#include "libxc_private.h"
-#include <asm-xeno/suspend.h>
-#include <zlib.h>
-
-/* This may allow us to create a 'quiet' command-line option, if necessary. */
-#define verbose_printf(_f, _a...) \
-    do {                          \
-        if ( !verbose ) break;    \
-        printf( _f , ## _a );     \
-        fflush(stdout);           \
-    } while ( 0 )
-
-static int get_pfn_list(
-    int domain_id, unsigned long *pfn_buf, unsigned long max_pfns)
-{
-    dom0_op_t op;
-    int ret;
-    op.cmd = DOM0_GETMEMLIST;
-    op.u.getmemlist.domain   = domain_id;
-    op.u.getmemlist.max_pfns = max_pfns;
-    op.u.getmemlist.buffer   = pfn_buf;
-
-    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
-    {
-        PERROR("Could not lock pfn list buffer");
-        return -1;
-    }    
-
-    ret = do_dom0_op(&op);
-
-    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
-
-    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
-}
-
-#define MAX_MMU_UPDATES 1024
-
-static int flush_mmu_updates(mmu_update_t *mmu_updates,
-                             int *mmu_update_idx)
-{
-    int err = 0;
-    privcmd_hypercall_t hypercall;
-
-    if ( *mmu_update_idx == 0 )
-        return 0;
-
-    hypercall.op     = __HYPERVISOR_mmu_update;
-    hypercall.arg[0] = (unsigned long)mmu_updates;
-    hypercall.arg[1] = (unsigned long)*mmu_update_idx;
-
-    if ( mlock(mmu_updates, sizeof(mmu_updates)) != 0 )
-    {
-        PERROR("Could not lock pagetable update array");
-        err = 1;
-        goto out;
-    }
-
-    if ( do_xen_hypercall(&hypercall) < 0 )
-    {
-        ERROR("Failure when submitting mmu updates");
-        err = 1;
-    }
-
-    *mmu_update_idx = 0;
-    
-    (void)munlock(mmu_updates, sizeof(mmu_updates));
-
- out:
-    return err;
-}
-
-static int add_mmu_update(mmu_update_t *mmu_updates,
-                          int *mmu_update_idx,
-                          unsigned long ptr, 
-                          unsigned long val)
-{
-    mmu_updates[*mmu_update_idx].ptr = ptr;
-    mmu_updates[*mmu_update_idx].val = val;
-    if ( ++*mmu_update_idx == MAX_MMU_UPDATES )
-        return flush_mmu_updates(mmu_updates, mmu_update_idx);
-    return 0;
-}
-
-static int checked_read(gzFile fd, void *buf, size_t count)
-{
-    int rc;
-    while ( ((rc = gzread(fd, buf, count)) == -1) && (errno == EINTR) )
-        continue;
-    return rc == count;
-}
-
-int xc_linux_restore(const char *state_file, int verbose)
-{
-    dom0_op_t op;
-    int rc = 1, i, j;
-    unsigned long mfn, pfn, dom = 0;
-    unsigned int prev_pc, this_pc;
-    
-    /* Number of page frames in use by this XenoLinux session. */
-    unsigned long nr_pfns;
-
-    /* The new domain's shared-info frame number. */
-    unsigned long shared_info_frame;
-    unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */
-    
-    /* A copy of the CPU context of the guest. */
-    full_execution_context_t ctxt;
-
-    /* First 16 bytes of the state file must contain 'XenoLinuxSuspend'. */
-    char signature[16];
-    
-    /* A copy of the domain's name. */
-    char name[MAX_DOMAIN_NAME];
-
-    /* A table containg the type of each PFN (/not/ MFN!). */
-    unsigned long *pfn_type = NULL;
-
-    /* A temporary mapping, and a copy, of one frame of guest memory. */
-    unsigned long *ppage, page[1024];
-
-    /* A copy of the pfn-to-mfn table frame list. */
-    unsigned long pfn_to_mfn_frame_list[1024];
-
-    /* A table mapping each PFN to its new MFN. */
-    unsigned long *pfn_to_mfn_table = NULL;
-
-    /* A temporary mapping of the guest's suspend record. */
-    suspend_record_t *p_srec;
-
-    /* The name and descriptor of the file that we are reading from. */
-    int    fd;
-    gzFile gfd;
-
-    mmu_update_t mmu_updates[MAX_MMU_UPDATES];
-    int mmu_update_idx = 0;
-
-    if ( (fd = open(state_file, O_RDONLY)) == -1 )
-    {
-        PERROR("Could not open state file for reading");
-        return 1;
-    }
-
-    if ( (gfd = gzdopen(fd, "rb")) == NULL )
-    {
-        ERROR("Could not allocate decompression state for state file");
-        close(fd);
-        return 1;
-    }
-
-    /* Start writing out the saved-domain record. */
-    if ( !checked_read(gfd, signature, 16) ||
-         (memcmp(signature, "XenoLinuxSuspend", 16) != 0) )
-    {
-        ERROR("Unrecognised state format -- no signature found");
-        goto out;
-    }
-
-    if ( !checked_read(gfd, name,                  sizeof(name)) ||
-         !checked_read(gfd, &nr_pfns,              sizeof(unsigned long)) ||
-         !checked_read(gfd, &ctxt,                 sizeof(ctxt)) ||
-         !checked_read(gfd, shared_info,           PAGE_SIZE) ||
-         !checked_read(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) )
-    {
-        ERROR("Error when reading from state file");
-        goto out;
-    }
-
-    for ( i = 0; i < MAX_DOMAIN_NAME; i++ )
-    {
-        if ( name[i] == '\0' ) break;
-        if ( name[i] & 0x80 )
-        {
-            ERROR("Random characters in domain name");
-            goto out;
-        }
-    }
-    name[MAX_DOMAIN_NAME-1] = '\0';
-
-    if ( nr_pfns > 1024*1024 )
-    {
-        ERROR("Invalid state file -- pfn count out of range");
-        goto out;
-    }
-
-    /* We want zeroed memory so use calloc rather than malloc. */
-    pfn_to_mfn_table = calloc(1, 4 * nr_pfns);
-    pfn_type         = calloc(1, 4 * nr_pfns);    
-
-    if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) )
-    {
-        errno = ENOMEM;
-        goto out;
-    }
-
-    if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) )
-    {
-        ERROR("Error when reading from state file");
-        goto out;
-    }
-
-    /* Create a new domain of the appropriate size, and find it's dom_id. */
-    op.cmd = DOM0_CREATEDOMAIN;
-    op.u.createdomain.memory_kb = nr_pfns * (PAGE_SIZE / 1024);
-    memcpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
-    if ( do_dom0_op(&op) < 0 )
-    {
-        ERROR("Could not create new domain");
-        goto out;
-    }
-    dom = op.u.createdomain.domain;
-
-    /* Get the domain's shared-info frame. */
-    op.cmd = DOM0_GETDOMAININFO;
-    op.u.getdomaininfo.domain = dom;
-    if ( do_dom0_op(&op) < 0 )
-    {
-        ERROR("Could not get information on new domain");
-        goto out;
-    }
-    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
-
-    if ( init_pfn_mapper() < 0 )
-        goto out;
-
-    /* Copy saved contents of shared-info page. No checking needed. */
-    ppage = map_pfn(shared_info_frame);
-    memcpy(ppage, shared_info, PAGE_SIZE);
-    unmap_pfn(ppage);
-
-    /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
-    if ( get_pfn_list(dom, pfn_to_mfn_table, nr_pfns) != nr_pfns )
-    {
-        ERROR("Did not read correct number of frame numbers for new dom");
-        goto out;
-    }
-
-    verbose_printf("Reloading memory pages:   0%%");
-
-    /*
-     * Now simply read each saved frame into its new machine frame.
-     * We uncanonicalise page tables as we go.
-     */
-    prev_pc = 0;
-    for ( i = 0; i < nr_pfns; i++ )
-    {
-        this_pc = (i * 100) / nr_pfns;
-        if ( (this_pc - prev_pc) >= 5 )
-        {
-            verbose_printf("\b\b\b\b%3d%%", this_pc);
-            prev_pc = this_pc;
-        }
-
-        mfn = pfn_to_mfn_table[i];
-
-        if ( !checked_read(gfd, page, PAGE_SIZE) )
-        {
-            ERROR("Error when reading from state file");
-            goto out;
-        }
-
-        ppage = map_pfn(mfn);
-        switch ( pfn_type[i] )
-        {
-        case L1TAB:
-            memset(ppage, 0, PAGE_SIZE);
-            if ( add_mmu_update(mmu_updates, &mmu_update_idx,
-                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
-                                MMUEXT_PIN_L1_TABLE) )
-                goto out;
-            for ( j = 0; j < 1024; j++ )
-            {
-                if ( page[j] & _PAGE_PRESENT )
-                {
-                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
-                    {
-                        ERROR("Frame number in page table is out of range");
-                        goto out;
-                    }
-                    if ( (pfn_type[pfn] != NONE) && (page[j] & _PAGE_RW) )
-                    {
-                        ERROR("Write access requested for a restricted frame");
-                        goto out;
-                    }
-                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
-                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
-                }
-                if ( add_mmu_update(mmu_updates, &mmu_update_idx,
-                                    (unsigned long)&ppage[j], page[j]) )
-                    goto out;
-            }
-            break;
-        case L2TAB:
-            memset(ppage, 0, PAGE_SIZE);
-            if ( add_mmu_update(mmu_updates, &mmu_update_idx,
-                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
-                                MMUEXT_PIN_L2_TABLE) )
-                goto out;
-            for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ )
-            {
-                if ( page[j] & _PAGE_PRESENT )
-                {
-                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
-                    {
-                        ERROR("Frame number in page table is out of range");
-                        goto out;
-                    }
-                    if ( pfn_type[pfn] != L1TAB )
-                    {
-                        ERROR("Page table mistyping");
-                        goto out;
-                    }
-                    /* Haven't reached the L1 table yet. Ensure it is safe! */
-                    if ( pfn > i )
-                    {
-                        unsigned long **l1 = map_pfn(pfn_to_mfn_table[pfn]);
-                        memset(l1, 0, PAGE_SIZE);
-                        unmap_pfn(l1);
-                    }
-                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE);
-                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
-                }
-                if ( add_mmu_update(mmu_updates, &mmu_update_idx,
-                                    (unsigned long)&ppage[j], page[j]) )
-                    goto out;
-            }
-            break;
-        default:
-            memcpy(ppage, page, PAGE_SIZE);
-            break;
-        }
-        /* NB. Must flush before unmapping page, as pass VAs to Xen. */
-        if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) )
-            goto out;
-        unmap_pfn(ppage);
-
-        if ( add_mmu_update(mmu_updates, &mmu_update_idx,
-                            (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) )
-            goto out;
-    }
-
-    if ( flush_mmu_updates(mmu_updates, &mmu_update_idx) )
-        goto out;
-
-    verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n");
-
-    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
-    pfn = ctxt.i386_ctxt.esi;
-    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
-    {
-        ERROR("Suspend record frame number is bad");
-        goto out;
-    }
-    ctxt.i386_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
-    p_srec = map_pfn(mfn);
-    p_srec->resume_info.nr_pages    = nr_pfns;
-    p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
-    p_srec->resume_info.dom_id      = dom;
-    p_srec->resume_info.flags       = 0;
-    unmap_pfn(p_srec);
-
-    /* Uncanonicalise each GDT frame number. */
-    if ( ctxt.gdt_ents > 8192 )
-    {
-        ERROR("GDT entry count out of range");
-        goto out;
-    }
-    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
-    {
-        pfn = ctxt.gdt_frames[i];
-        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
-        {
-            ERROR("GDT frame number is bad");
-            goto out;
-        }
-        ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
-    }
-
-    /* Uncanonicalise the page table base pointer. */
-    pfn = ctxt.pt_base >> PAGE_SHIFT;
-    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) )
-    {
-        ERROR("PT base is bad");
-        goto out;
-    }
-    ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
-
-    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
-    for ( i = 0; i < nr_pfns; i += 1024 )
-    {
-        unsigned long copy_size = (nr_pfns - i) * sizeof(unsigned long);
-        if ( copy_size > PAGE_SIZE ) copy_size = PAGE_SIZE;
-        pfn = pfn_to_mfn_frame_list[i/1024];
-        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
-        {
-            ERROR("PFN-to-MFN frame number is bad");
-            goto out;
-        }
-        ppage = map_pfn(pfn_to_mfn_table[pfn]);
-        memcpy(ppage, &pfn_to_mfn_table[i], copy_size);        
-        unmap_pfn(ppage);
-    }
-
-    /*
-     * Safety checking of saved context:
-     *  1. i386_ctxt is fine, as Xen checks that on context switch.
-     *  2. i387_ctxt is fine, as it can't hurt Xen.
-     *  3. trap_ctxt needs the code selectors checked.
-     *  4. fast_trap_idx is checked by Xen.
-     *  5. ldt base must be page-aligned, no more than 8192 ents, ...
-     *  6. gdt already done, and further checking is done by Xen.
-     *  7. check that ring1_ss is safe.
-     *  8. pt_base is already done.
-     *  9. debugregs are checked by Xen.
-     *  10. callback code selectors need checking.
-     */
-    for ( i = 0; i < 256; i++ )
-    {
-        ctxt.trap_ctxt[i].vector = i;
-        if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
-            ctxt.trap_ctxt[i].cs = FLAT_RING1_CS;
-    }
-    if ( (ctxt.ring1_ss & 3) == 0 )
-        ctxt.ring1_ss = FLAT_RING1_DS;
-    if ( (ctxt.event_callback_cs & 3) == 0 )
-        ctxt.event_callback_cs = FLAT_RING1_CS;
-    if ( (ctxt.failsafe_callback_cs & 3) == 0 )
-        ctxt.failsafe_callback_cs = FLAT_RING1_CS;
-    if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
-         (ctxt.ldt_ents > 8192) ||
-         (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
-         ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
-    {
-        ERROR("Bad LDT base or size");
-        goto out;
-    }
-
-    op.cmd = DOM0_BUILDDOMAIN;
-    op.u.builddomain.domain   = dom;
-    op.u.builddomain.num_vifs = 1;
-    memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt));
-    rc = do_dom0_op(&op);
-
- out:
-    if ( rc != 0 )
-    {
-        if ( dom != 0 )
-        {
-            op.cmd = DOM0_DESTROYDOMAIN;
-            op.u.destroydomain.domain = dom;
-            op.u.destroydomain.force  = 1;
-            (void)do_dom0_op(&op);
-        }
-    }
-    else
-    {
-        /* Success: print the domain id. */
-        verbose_printf("DOM=%ld\n", dom);
-    }
-
-    if ( pfn_to_mfn_table != NULL )
-        free(pfn_to_mfn_table);
-    if ( pfn_type != NULL )
-        free(pfn_type);
-
-    gzclose(gfd);
-
-    return (rc == 0) ? dom : rc;
-}
diff --git a/tools/libxc/libxc_linux_save.c b/tools/libxc/libxc_linux_save.c
deleted file mode 100644 (file)
index 77edfc6..0000000
+++ /dev/null
@@ -1,380 +0,0 @@
-/******************************************************************************
- * libxc_linux_save.c
- * 
- * Save the state of a running Xenolinux session.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#include "libxc_private.h"
-#include <asm-xeno/suspend.h>
-#include <zlib.h>
-
-/* This may allow us to create a 'quiet' command-line option, if necessary. */
-#define verbose_printf(_f, _a...) \
-    do {                          \
-        if ( !verbose ) break;    \
-        printf( _f , ## _a );     \
-        fflush(stdout);           \
-    } while ( 0 )
-
-/*
- * Returns TRUE if the given machine frame number has a unique mapping
- * in the guest's pseudophysical map.
- */
-#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \
-    (((_mfn) < (1024*1024)) &&          \
-     (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn)))
-
-/* Returns TRUE if MFN is successfully converted to a PFN. */
-#define translate_mfn_to_pfn(_pmfn)         \
-({                                          \
-    unsigned long mfn = *(_pmfn);           \
-    int _res = 1;                           \
-    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )   \
-        _res = 0;                           \
-    else                                    \
-        *(_pmfn) = mfn_to_pfn_table[mfn];   \
-    _res;                                   \
-})
-
-static int check_pfn_ownership(unsigned long mfn, unsigned int dom)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_GETPAGEFRAMEINFO;
-    op.u.getpageframeinfo.pfn = mfn;
-    if ( (do_dom0_op(&op) < 0) || (op.u.getpageframeinfo.domain != dom) )
-        return 0;
-    return 1;
-}
-
-#define GETPFN_ERR (~0U)
-static unsigned int get_pfn_type(unsigned long mfn)
-{
-    dom0_op_t op;
-    op.cmd = DOM0_GETPAGEFRAMEINFO;
-    op.u.getpageframeinfo.pfn = mfn;
-    if ( do_dom0_op(&op) < 0 )
-    {
-        PERROR("Unexpected failure when getting page frame info!");
-        return GETPFN_ERR;
-    }
-    return op.u.getpageframeinfo.type;
-}
-
-static int checked_write(gzFile fd, void *buf, size_t count)
-{
-    int rc;
-    while ( ((rc = gzwrite(fd, buf, count)) == -1) && (errno = EINTR) )
-        continue;
-    return rc == count;
-}
-
-int xc_linux_save(unsigned int domid, const char *state_file, int verbose)
-{
-    dom0_op_t op;
-    int rc = 1, i, j;
-    unsigned long mfn;
-    unsigned int prev_pc, this_pc;
-
-    /* Remember if we stopped the guest, so we can restart it on exit. */
-    int we_stopped_it = 0;
-
-    /* The new domain's shared-info frame number. */
-    unsigned long shared_info_frame;
-    
-    /* A copy of the CPU context of the guest. */
-    full_execution_context_t ctxt;
-
-    /* A copy of the domain's name. */
-    char name[MAX_DOMAIN_NAME];
-
-    /* A table containg the type of each PFN (/not/ MFN!). */
-    unsigned long *pfn_type = NULL;
-
-    /* A temporary mapping, and a copy, of one frame of guest memory. */
-    unsigned long *ppage, page[1024];
-
-    /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */
-    unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024];
-    /* A temporary mapping of one frame in the above list. */
-    unsigned long *pfn_to_mfn_frame;
-
-    /* A table mapping each PFN to its current MFN. */
-    unsigned long *pfn_to_mfn_table = NULL;
-    /* A table mapping each current MFN to its canonical PFN. */
-    unsigned long *mfn_to_pfn_table = NULL;
-    
-    /* A temporary mapping, and a copy, of the guest's suspend record. */
-    suspend_record_t *p_srec, srec;
-
-    /* The name and descriptor of the file that we are writing to. */
-    int    fd;
-    gzFile gfd;
-
-    if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
-    {
-        PERROR("Could not open file for writing");
-        return 1;
-    }
-
-    /*
-     * Compression rate 1: we want speed over compression. We're mainly going
-     * for those zero pages, after all.
-     */
-    if ( (gfd = gzdopen(fd, "wb1")) == NULL )
-    {
-        ERROR("Could not allocate compression state for state file");
-        close(fd);
-        return 1;
-    }
-
-    /* Ensure that the domain exists, and that it is stopped. */
-    for ( ; ; )
-    {
-        op.cmd = DOM0_GETDOMAININFO;
-        op.u.getdomaininfo.domain = domid;
-        if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domid) )
-        {
-            PERROR("Could not get info on domain");
-            goto out;
-        }
-
-        memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt));
-        memcpy(name, op.u.getdomaininfo.name, sizeof(name));
-        shared_info_frame = op.u.getdomaininfo.shared_info_frame;
-
-        if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
-            break;
-
-        we_stopped_it = 1;
-
-        op.cmd = DOM0_STOPDOMAIN;
-        op.u.stopdomain.domain = domid;
-        (void)do_dom0_op(&op);
-
-        sleep(1);
-    }
-
-    /* A cheesy test to see whether the domain contains valid state. */
-    if ( ctxt.pt_base == 0 )
-    {
-        ERROR("Domain is not in a valid Xenolinux state");
-        goto out;
-    }
-
-    if ( init_pfn_mapper() < 0 )
-        goto out;
-
-    /* Is the suspend-record MFN actually valid for this domain? */
-    if ( !check_pfn_ownership(ctxt.i386_ctxt.esi, domid) )
-    {
-        ERROR("Invalid state record pointer");
-        goto out;
-    }
-
-    /* If the suspend-record MFN is okay then grab a copy of it to @srec. */
-    p_srec = map_pfn(ctxt.i386_ctxt.esi);
-    memcpy(&srec, p_srec, sizeof(srec));
-    unmap_pfn(p_srec);
-
-    if ( srec.nr_pfns > 1024*1024 )
-    {
-        ERROR("Invalid state record -- pfn count out of range");
-        goto out;
-    }
-
-    if ( !check_pfn_ownership(srec.pfn_to_mfn_frame_list, domid) )
-    {
-        ERROR("Invalid pfn-to-mfn frame list pointer");
-        goto out;
-    }
-
-    /* Grab a copy of the pfn-to-mfn table frame list. */
-    p_pfn_to_mfn_frame_list = map_pfn(srec.pfn_to_mfn_frame_list);
-    memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE);
-    unmap_pfn(p_pfn_to_mfn_frame_list);
-
-    /* We want zeroed memory so use calloc rather than malloc. */
-    mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024);
-    pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns);
-    pfn_type         = calloc(1, 4 * srec.nr_pfns);
-
-    if ( (mfn_to_pfn_table == NULL) ||
-         (pfn_to_mfn_table == NULL) ||
-         (pfn_type == NULL) )
-    {
-        errno = ENOMEM;
-        goto out;
-    }
-
-
-    /*
-     * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
-     * loop we have each MFN mapped at most once. Note that there may be MFNs
-     * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
-     */
-    pfn_to_mfn_frame = NULL;
-    for ( i = 0; i < srec.nr_pfns; i++ )
-    {
-        /* Each frameful of table frames must be checked & mapped on demand. */
-        if ( (i & 1023) == 0 )
-        {
-            mfn = pfn_to_mfn_frame_list[i/1024];
-            if ( !check_pfn_ownership(mfn, domid) )
-            {
-                ERROR("Invalid frame number if pfn-to-mfn frame list");
-                goto out;
-            }
-            if ( pfn_to_mfn_frame != NULL )
-                unmap_pfn(pfn_to_mfn_frame);
-            pfn_to_mfn_frame = map_pfn(mfn);
-        }
-        
-        mfn = pfn_to_mfn_frame[i & 1023];
-
-        if ( !check_pfn_ownership(mfn, domid) )
-        {
-            ERROR("Invalid frame specified with pfn-to-mfn table");
-            goto out;
-        }
-
-        /* Did we map this MFN already? That would be invalid! */
-        if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
-        {
-            ERROR("A machine frame appears twice in pseudophys space");
-            goto out;
-        }
-
-        pfn_to_mfn_table[i] = mfn;
-        mfn_to_pfn_table[mfn] = i;
-
-        /* Query page type by MFN, but store it by PFN. */
-        if ( (pfn_type[i] = get_pfn_type(mfn)) == GETPFN_ERR )
-            goto out;
-    }
-
-    /* Canonicalise the suspend-record frame number. */
-    if ( !translate_mfn_to_pfn(&ctxt.i386_ctxt.esi) )
-    {
-        ERROR("State record is not in range of pseudophys map");
-        goto out;
-    }
-
-    /* Canonicalise each GDT frame number. */
-    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
-    {
-        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) )
-        {
-            ERROR("GDT frame is not in range of pseudophys map");
-            goto out;
-        }
-    }
-
-    /* Canonicalise the page table base pointer. */
-    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) )
-    {
-        ERROR("PT base is not in range of pseudophys map");
-        goto out;
-    }
-    ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
-
-    /* Canonicalise the pfn-to-mfn table frame-number list. */
-    for ( i = 0; i < srec.nr_pfns; i += 1024 )
-    {
-        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
-        {
-            ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
-            goto out;
-        }
-    }
-
-    /* Start writing out the saved-domain record. */
-    ppage = map_pfn(shared_info_frame);
-    if ( !checked_write(gfd, "XenoLinuxSuspend",    16) ||
-         !checked_write(gfd, name,                  sizeof(name)) ||
-         !checked_write(gfd, &srec.nr_pfns,         sizeof(unsigned long)) ||
-         !checked_write(gfd, &ctxt,                 sizeof(ctxt)) ||
-         !checked_write(gfd, ppage,                 PAGE_SIZE) ||
-         !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ||
-         !checked_write(gfd, pfn_type,              4 * srec.nr_pfns) )
-    {
-        ERROR("Error when writing to state file");
-        goto out;
-    }
-    unmap_pfn(ppage);
-
-    verbose_printf("Saving memory pages:   0%%");
-
-    /* Now write out each data page, canonicalising page tables as we go... */
-    prev_pc = 0;
-    for ( i = 0; i < srec.nr_pfns; i++ )
-    {
-        this_pc = (i * 100) / srec.nr_pfns;
-        if ( (this_pc - prev_pc) >= 5 )
-        {
-            verbose_printf("\b\b\b\b%3d%%", this_pc);
-            prev_pc = this_pc;
-        }
-
-        mfn = pfn_to_mfn_table[i];
-
-        ppage = map_pfn(mfn);
-        memcpy(page, ppage, PAGE_SIZE);
-        unmap_pfn(ppage);
-
-        if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
-        {
-            for ( j = 0; 
-                  j < ((pfn_type[i] == L2TAB) ? 
-                       (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
-                  j++ )
-            {
-                if ( !(page[j] & _PAGE_PRESENT) ) continue;
-                mfn = page[j] >> PAGE_SHIFT;
-                if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
-                {
-                    ERROR("Frame number in pagetable page is invalid");
-                    goto out;
-                }
-                page[j] &= PAGE_SIZE - 1;
-                page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
-            }
-        }
-
-        if ( !checked_write(gfd, page, PAGE_SIZE) )
-        {
-            ERROR("Error when writing to state file");
-            goto out;
-        }
-    }
-
-    verbose_printf("\b\b\b\b100%%\nMemory saved.\n");
-
-    /* Success! */
-    rc = 0;
-
- out:
-    /* Restart the domain if we had to stop it to save its state. */
-    if ( we_stopped_it )
-    {
-        op.cmd = DOM0_STARTDOMAIN;
-        op.u.startdomain.domain = domid;
-        (void)do_dom0_op(&op);
-    }
-
-    gzclose(gfd);
-
-    if ( pfn_to_mfn_table != NULL )
-        free(pfn_to_mfn_table);
-    if ( mfn_to_pfn_table != NULL )
-        free(mfn_to_pfn_table);
-    if ( pfn_type != NULL )
-        free(pfn_type);
-
-    /* On error, make sure the file is deleted. */
-    if ( rc != 0 )
-        unlink(state_file);
-    
-    return !!rc;
-}
diff --git a/tools/libxc/libxc_misc.c b/tools/libxc/libxc_misc.c
deleted file mode 100644 (file)
index 351fb26..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/******************************************************************************
- * libxc_misc.c
- * 
- * Miscellaneous control interface functions.
- */
-
-#include "libxc_private.h"
-
-int privcmd_fd = -1;
-
-int xc_interface_open(void)
-{
-    if ( (privcmd_fd == -1) &&
-         ((privcmd_fd = open("/proc/xeno/privcmd", O_RDWR)) < 0) )
-    {
-        privcmd_fd = -1;
-        return -1;
-    }
-    return 0;
-}
-
-int xc_interface_close(void)
-{
-    if ( privcmd_fd != -1 )
-    {
-        close(privcmd_fd);
-        privcmd_fd = -1;
-    }
-    return 0;
-}
-
-
-#define CONSOLE_RING_CLEAR     1
-
-int xc_readconsolering(char *str, unsigned int max_chars, int clear)
-{
-    int ret;
-    dom0_op_t op;
-
-    op.cmd = DOM0_READCONSOLE;
-    op.u.readconsole.str = (unsigned long)str;
-    op.u.readconsole.count = max_chars;
-    op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
-
-    if ( (ret = do_dom0_op(&op)) > 0 )
-        str[ret] = '\0';
-
-    return ret;
-}    
-
diff --git a/tools/libxc/libxc_private.c b/tools/libxc/libxc_private.c
deleted file mode 100644 (file)
index c4c9c8b..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/******************************************************************************
- * libxc_private.c
- * 
- * Helper functions for the rest of the library.
- */
-
-#include "libxc_private.h"
-
-static int devmem_fd = -1;
-
-int init_pfn_mapper(void)
-{
-    if ( (devmem_fd == -1) &&
-         ((devmem_fd = open("/dev/mem", O_RDWR)) < 0) )
-    {
-        devmem_fd = -1;
-        return -1;
-    }
-    return 0;
-}
-
-void *map_pfn(unsigned long pfn)
-{
-    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
-                       MAP_SHARED, devmem_fd, pfn << PAGE_SHIFT);
-    if ( vaddr == MAP_FAILED )
-        return NULL;
-    return vaddr;
-}
-
-void unmap_pfn(void *vaddr)
-{
-    (void)munmap(vaddr, PAGE_SIZE);
-}
diff --git a/tools/libxc/libxc_private.h b/tools/libxc/libxc_private.h
deleted file mode 100644 (file)
index d1994f5..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-
-#ifndef __LIBXC_PRIVATE_H__
-#define __LIBXC_PRIVATE_H__
-
-typedef unsigned char      u8;
-typedef unsigned short     u16;
-typedef unsigned long      u32;
-typedef unsigned long long u64;
-typedef signed char        s8;
-typedef signed short       s16;
-typedef signed long        s32;
-typedef signed long long   s64;
-
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <string.h>
-
-#include "xc.h"
-
-#include <asm-xeno/proc_cmd.h>
-#include <hypervisor-ifs/hypervisor-if.h>
-#include <hypervisor-ifs/dom0_ops.h>
-#include <hypervisor-ifs/vbd.h>
-
-#define _PAGE_PRESENT   0x001
-#define _PAGE_RW        0x002
-#define _PAGE_USER      0x004
-#define _PAGE_PWT       0x008
-#define _PAGE_PCD       0x010
-#define _PAGE_ACCESSED  0x020
-#define _PAGE_DIRTY     0x040
-#define _PAGE_PAT       0x080
-#define _PAGE_PSE       0x080
-#define _PAGE_GLOBAL    0x100
-
-
-#define L1_PAGETABLE_SHIFT       12
-#define L2_PAGETABLE_SHIFT       22
-#define ENTRIES_PER_L1_PAGETABLE 1024
-#define ENTRIES_PER_L2_PAGETABLE 1024
-#define PAGE_SHIFT              L1_PAGETABLE_SHIFT
-#define PAGE_SIZE               (1UL << PAGE_SHIFT)
-#define PAGE_MASK               (~(PAGE_SIZE-1))
-
-typedef struct { unsigned long l1_lo; } l1_pgentry_t;
-typedef struct { unsigned long l2_lo; } l2_pgentry_t;
-
-#define l1_table_offset(_a) \
-          (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
-#define l2_table_offset(_a) \
-          ((_a) >> L2_PAGETABLE_SHIFT)
-
-#define ERROR(_m)  \
-    fprintf(stderr, "ERROR: %s\n", (_m))
-
-#define PERROR(_m) \
-    fprintf(stderr, "ERROR: %s (%d = %s)\n", (_m), errno, strerror(errno))
-
-extern int privcmd_fd;
-static inline int do_privcmd(unsigned int cmd, unsigned long data)
-{
-    return ioctl(privcmd_fd, cmd, data);
-}
-
-static inline int do_xen_hypercall(privcmd_hypercall_t *hypercall)
-{
-    return do_privcmd(IOCTL_PRIVCMD_HYPERCALL, (unsigned long)hypercall);
-}
-
-static inline int do_dom0_op(dom0_op_t *op)
-{
-    int ret = -1;
-    privcmd_hypercall_t hypercall;
-
-    op->interface_version = DOM0_INTERFACE_VERSION;
-
-    hypercall.op     = __HYPERVISOR_dom0_op;
-    hypercall.arg[0] = (unsigned long)op;
-
-    if ( mlock(op, sizeof(*op)) != 0 )
-        goto out1;
-
-    if ( (ret = do_xen_hypercall(&hypercall)) < 0 )
-    {
-        if ( errno == EACCES )
-            fprintf(stderr, "Dom0 operation failed -- need to"
-                    " rebuild the user-space tool set?\n");
-        goto out2;
-    }
-
-    ret = 0;
-
- out2: (void)munlock(op, sizeof(*op));
- out1: return ret;
-}
-
-static inline int do_network_op(network_op_t *op)
-{
-    int ret = -1;
-    privcmd_hypercall_t hypercall;
-
-    hypercall.op     = __HYPERVISOR_network_op;
-    hypercall.arg[0] = (unsigned long)op;
-
-    if ( mlock(op, sizeof(*op)) != 0 )
-        goto out1;
-
-    if ( (ret = do_xen_hypercall(&hypercall)) < 0 )
-        goto out2;
-
-    ret = 0;
-
- out2: (void)munlock(op, sizeof(*op));
- out1: return ret;
-}
-
-
-static inline int do_block_io_op(block_io_op_t *op)
-{
-    int ret = -1;
-    privcmd_hypercall_t hypercall;
-
-    hypercall.op     = __HYPERVISOR_block_io_op;
-    hypercall.arg[0] = (unsigned long)op;
-
-    if ( mlock(op, sizeof(*op)) != 0 )
-        goto out1;
-
-    if ( do_xen_hypercall(&hypercall) < 0 )
-        goto out2;
-
-    ret = 0;
-
- out2: (void)munlock(op, sizeof(*op));
- out1: return ret;
-}
-
-/*
- * PFN mapping.
- */
-int init_pfn_mapper(void);
-void *map_pfn(unsigned long pfn);
-void unmap_pfn(void *vaddr);
-
-#endif /* __LIBXC_PRIVATE_H__ */
diff --git a/tools/libxc/libxc_vbd.c b/tools/libxc/libxc_vbd.c
deleted file mode 100644 (file)
index c255f5b..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/******************************************************************************
- * libxc_vbd.c
- * 
- * API for manipulating and accessing per-domain virtual block devices.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#define _GNU_SOURCE
-#include "libxc_private.h"
-
-int xc_vbd_create(unsigned int domid, unsigned short vbdid, int writeable)
-{
-    block_io_op_t op; 
-    op.cmd = BLOCK_IO_OP_VBD_CREATE; 
-    op.u.create_params.domain  = domid;
-    op.u.create_params.vdevice = vbdid;
-    op.u.create_params.mode    = VBD_MODE_R | (writeable ? VBD_MODE_W : 0);
-    return do_block_io_op(&op);
-}
-
-
-int xc_vbd_destroy(unsigned int domid, unsigned short vbdid)
-{
-    block_io_op_t op; 
-    op.cmd = BLOCK_IO_OP_VBD_DELETE; 
-    op.u.delete_params.domain  = domid;
-    op.u.delete_params.vdevice = vbdid;
-    return do_block_io_op(&op);
-}
-
-
-int xc_vbd_add_extent(unsigned int domid, 
-                      unsigned short vbdid,
-                      unsigned short real_device,
-                      unsigned long start_sector,
-                      unsigned long nr_sectors)
-{
-    block_io_op_t op; 
-    op.cmd = BLOCK_IO_OP_VBD_ADD; 
-    op.u.add_params.domain  = domid; 
-    op.u.add_params.vdevice = vbdid;
-    op.u.add_params.extent.device       = real_device; 
-    op.u.add_params.extent.start_sector = start_sector;
-    op.u.add_params.extent.nr_sectors   = nr_sectors;
-    return do_block_io_op(&op);
-}
-
-
-int xc_vbd_delete_extent(unsigned int domid, 
-                         unsigned short vbdid,
-                         unsigned short real_device,
-                         unsigned long start_sector,
-                         unsigned long nr_sectors)
-{
-    block_io_op_t op; 
-    op.cmd = BLOCK_IO_OP_VBD_REMOVE; 
-    op.u.add_params.domain  = domid; 
-    op.u.add_params.vdevice = vbdid;
-    op.u.add_params.extent.device       = real_device; 
-    op.u.add_params.extent.start_sector = start_sector;
-    op.u.add_params.extent.nr_sectors   = nr_sectors;
-    return do_block_io_op(&op);
-}
-
-
-int xc_vbd_probe(unsigned int domid,
-                 unsigned short vbdid,
-                 unsigned int max_vbds,
-                 xc_vbd_t *vbds)
-{
-    block_io_op_t op; 
-    xen_disk_info_t *xdi = &op.u.probe_params.xdi; 
-    int i, j, ret, allocsz = max_vbds * sizeof(xen_disk_t); 
-
-    op.cmd = BLOCK_IO_OP_VBD_PROBE; 
-    op.u.probe_params.domain    = domid; 
-    
-    xdi->max   = max_vbds;
-    xdi->disks = malloc(allocsz);
-    xdi->count = 0;
-
-    if ( (xdi->disks == NULL) || (mlock(xdi->disks, allocsz) != 0) )
-    {
-        if ( xdi->disks != NULL )
-            free(xdi->disks);
-        return -ENOMEM;
-    }
-
-    ret = do_block_io_op(&op);
-
-    (void)munlock(xdi->disks, allocsz);
-
-    if ( ret >= 0 )
-    {
-       for ( i = 0, j = 0; i < xdi->count; i++ )
-        {
-            if ( !(xdi->disks[i].info & XD_FLAG_VIRT) )
-                continue;
-            
-            vbds[j].domid = xdi->disks[i].domain;
-            vbds[j].vbdid = xdi->disks[i].device;
-            vbds[j].flags = (xdi->disks[i].info & XD_FLAG_RO) ? 
-                0 : XC_VBDF_WRITEABLE;
-            vbds[j].nr_sectors = xdi->disks[i].capacity;
-            
-            j++;
-        }
-
-        ret = j;
-    }
-    
-    free(xdi->disks);
-
-    return ret;
-}
diff --git a/tools/libxc/libxc_vif.c b/tools/libxc/libxc_vif.c
deleted file mode 100644 (file)
index c9d35e5..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/******************************************************************************
- * libxc_vif.c
- * 
- * API for manipulating and accessing per-network-interface parameters.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#include "libxc_private.h"
-
-int xc_vif_scheduler_set(unsigned int domid, 
-                         unsigned int vifid, 
-                         xc_vif_sched_params_t *params)
-{
-    network_op_t  netop;
-    netop.cmd = NETWORK_OP_VIFSETPARAMS;
-    netop.u.vif_setparams.domain       = domid;
-    netop.u.vif_setparams.vif          = vifid;
-    netop.u.vif_setparams.credit_bytes = params->credit_bytes;
-    netop.u.vif_setparams.credit_usec  = params->credit_usec;
-    return do_network_op(&netop);
-}
-
-
-int xc_vif_scheduler_get(unsigned int domid, 
-                         unsigned int vifid, 
-                         xc_vif_sched_params_t *params)
-{
-    network_op_t  netop;
-    int rc;
-
-    netop.cmd = NETWORK_OP_VIFGETINFO;
-    netop.u.vif_getinfo.domain = domid;
-    netop.u.vif_getinfo.vif    = vifid;
-
-    if ( (rc = do_network_op(&netop)) >= 0 )
-    {
-        params->credit_bytes = netop.u.vif_getinfo.credit_bytes;
-        params->credit_usec  = netop.u.vif_getinfo.credit_usec;
-    }
-
-    return rc;
-}
-
-
-int xc_vif_stats_get(unsigned int domid, 
-                     unsigned int vifid, 
-                     xc_vif_stats_t *stats)
-{
-    network_op_t  netop;
-    int rc;
-
-    netop.cmd = NETWORK_OP_VIFGETINFO;
-    netop.u.vif_getinfo.domain = domid;
-    netop.u.vif_getinfo.vif    = vifid;
-
-    if ( (rc = do_network_op(&netop)) >= 0 )
-    {
-        stats->tx_bytes = netop.u.vif_getinfo.total_bytes_sent;
-        stats->tx_pkts  = netop.u.vif_getinfo.total_packets_sent;
-        stats->rx_bytes = netop.u.vif_getinfo.total_bytes_received;
-        stats->rx_pkts  = netop.u.vif_getinfo.total_packets_received;
-    }
-
-    return rc;
-}
diff --git a/tools/libxc/rpm.spec b/tools/libxc/rpm.spec
deleted file mode 100644 (file)
index 1b4c5fc..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-Summary: Xen control interface library
-Name: xen-internal-library
-Version: 1.2
-Release: 1
-License: Xen
-Group: Xen
-BuildRoot: %{staging}
-%description
-Library to make it easier to access the Xen control interfaces.
-
-%pre
-%preun
-%install
-install -m 0755 -d $RPM_BUILD_ROOT/lib
-install -m 0755 libxc.a $RPM_BUILD_ROOT/lib/libxc.a
-install -m 0755 libxc.so $RPM_BUILD_ROOT/lib/libxc.so
-install -m 0755 -d $RPM_BUILD_ROOT/include
-install -m 0644 xc.h $RPM_BUILD_ROOT/include/xc.h
-%clean
-%post
-%postun
-%files
-%defattr(-,root,root)
-%dir /lib
-/lib/libxc.a
-/lib/libxc.so
-%dir /include
-/include/xc.h
diff --git a/tools/libxc/xc.h b/tools/libxc/xc.h
deleted file mode 100644 (file)
index 73934ad..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/******************************************************************************
- * xc.h
- * 
- * A library for low-level access to the Xen control interfaces.
- * 
- * Copyright (c) 2003, K A Fraser.
- */
-
-#ifndef __XC_H__
-#define __XC_H__
-
-int xc_interface_open(void);
-int xc_interface_close(void);
-
-typedef struct {
-    unsigned int  domid;
-    unsigned int  cpu;
-    int           has_cpu;
-    int           stopped;
-    unsigned long nr_pages;
-    unsigned long long cpu_time;
-#define XC_DOMINFO_MAXNAME 16
-    char          name[XC_DOMINFO_MAXNAME];
-} xc_dominfo_t;
-
-int xc_domain_create(unsigned int mem_kb, const char *name);
-int xc_domain_start(unsigned int domid);
-int xc_domain_stop(unsigned int domid);
-int xc_domain_destroy(unsigned int domid, int force);
-int xc_domain_getinfo(unsigned int first_domid, 
-                      unsigned int max_doms,
-                      xc_dominfo_t *info);
-
-int xc_linux_save(unsigned int domid, const char *state_file, int verbose);
-int xc_linux_restore(const char *state_file, int verbose);
-int xc_linux_build(unsigned int domid,
-                   const char *image_name,
-                   const char *ramdisk_name,
-                   const char *cmdline,
-                   int verbose);
-
-int xc_bvtsched_global_set(unsigned long ctx_allow);
-int xc_bvtsched_domain_set(unsigned int domid,
-                           unsigned long mcuadv,
-                           unsigned long warp,
-                           unsigned long warpl,
-                           unsigned long warpu);
-
-typedef struct {
-    unsigned long credit_bytes;
-    unsigned long credit_usec;
-} xc_vif_sched_params_t;
-
-typedef struct {
-    unsigned long long tx_bytes, tx_pkts;
-    unsigned long long rx_bytes, rx_pkts;
-} xc_vif_stats_t;
-
-int xc_vif_scheduler_set(unsigned int domid, 
-                         unsigned int vifid,
-                         xc_vif_sched_params_t *params);
-int xc_vif_scheduler_get(unsigned int domid, 
-                         unsigned int vifid,
-                         xc_vif_sched_params_t *params);
-int xc_vif_stats_get(unsigned int domid, 
-                         unsigned int vifid,
-                         xc_vif_stats_t *stats);
-
-typedef struct {
-#define XC_VBDDOM_PROBE_ALL (~0U)
-    unsigned int   domid;
-    unsigned short vbdid;
-#define XC_VBDF_WRITEABLE (1<<0)
-    unsigned long  flags;
-    unsigned long  nr_sectors;
-} xc_vbd_t;
-
-
-int xc_vbd_create(unsigned int domid, unsigned short vbdid, int writeable);
-int xc_vbd_destroy(unsigned int domid, unsigned short vbdid);
-int xc_vbd_add_extent(unsigned int domid, 
-                      unsigned short vbdid,
-                      unsigned short real_device,
-                      unsigned long start_sector,
-                      unsigned long nr_sectors);
-int xc_vbd_delete_extent(unsigned int domid, 
-                         unsigned short vbdid,
-                         unsigned short real_device,
-                         unsigned long start_sector,
-                         unsigned long nr_sectors);
-int xc_vbd_probe(unsigned int domid,
-                 unsigned short vbdid,
-                 unsigned int max_vbds,
-                 xc_vbd_t *vbds);
-
-int xc_readconsolering(char *str, unsigned int max_chars, int clear);
-
-
-#endif /* __XC_H__ */
diff --git a/tools/xc/Makefile b/tools/xc/Makefile
new file mode 100644 (file)
index 0000000..81bd394
--- /dev/null
@@ -0,0 +1,9 @@
+
+all:
+       $(MAKE) -C lib
+
+install:
+       $(MAKE) -C lib install
+
+clean:
+       $(MAKE) -C lib xlean
diff --git a/tools/xc/lib/Makefile b/tools/xc/lib/Makefile
new file mode 100644 (file)
index 0000000..24121c9
--- /dev/null
@@ -0,0 +1,48 @@
+
+CC       = gcc
+CFLAGS   = -c -Wall -O3 
+CFLAGS  += -I../../../xen/include -I../../../xenolinux-sparse/include
+
+HDRS     = $(wildcard *.h)
+OBJS     = $(patsubst %.c,%.o,$(wildcard libxc_*.c))
+
+LIBS     = libxc.a libxc.so
+
+all: check-for-zlib $(LIBS)
+       ranlib libxc.a
+
+check-for-zlib:
+       @if [ ! -e /usr/include/zlib.h ]; then \
+       echo "***********************************************************"; \
+       echo "ERROR: install zlib header files (http://www.gzip.org/zlib)"; \
+       echo "***********************************************************"; \
+       false; \
+       fi
+
+install: all
+       mkdir -p ../../../../install/lib
+       mkdir -p ../../../../install/include
+       cp -a $(LIBS) ../../../../install/lib
+       for i in $(LIBS) do ; chmod 755 ../../../../install/bin/$i ; done
+       cp -a xc.h ../../../../install/include
+       chmod 644 ../../../../install/include/xc.h
+
+clean:
+       $(RM) *.a *.so *.o *.rpm $(LIBS)
+
+rpm: all
+       rm -rf staging
+       mkdir staging
+       mkdir staging/i386
+       rpmbuild --define "staging$$PWD/staging" --define '_builddir.' \
+               --define "_rpmdir$$PWD/staging" -bb rpm.spec
+       mv staging/i386/*.rpm .
+       rm -rf staging
+
+libxc.so: $(OBJS)
+       $(LD) -shared -o $@ $^ -lz
+
+libxc.a: libxc.a($(OBJS))
+
+%.o: %.c $(HDRS) Makefile
+       $(CC) $(CFLAGS) -o $@ $<
diff --git a/tools/xc/lib/libxc_bvtsched.c b/tools/xc/lib/libxc_bvtsched.c
new file mode 100644 (file)
index 0000000..f7d5b26
--- /dev/null
@@ -0,0 +1,35 @@
+/******************************************************************************
+ * libxc_bvtsched.c
+ * 
+ * API for manipulating parameters of the Borrowed Virtual Time scheduler.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#include "libxc_private.h"
+
+int xc_bvtsched_global_set(int xc_handle,
+                           unsigned long ctx_allow)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_BVTCTL;
+    op.u.bvtctl.ctx_allow = ctx_allow;
+    return do_dom0_op(xc_handle, &op);
+}
+
+int xc_bvtsched_domain_set(int xc_handle,
+                           unsigned int domid,
+                           unsigned long mcuadv,
+                           unsigned long warp,
+                           unsigned long warpl,
+                           unsigned long warpu)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_ADJUSTDOM;
+    op.u.adjustdom.domain  = domid;
+    op.u.adjustdom.mcu_adv = mcuadv;
+    op.u.adjustdom.warp    = warp;
+    op.u.adjustdom.warpl   = warpl;
+    op.u.adjustdom.warpu   = warpu;
+    return do_dom0_op(xc_handle, &op);
+}
diff --git a/tools/xc/lib/libxc_domain.c b/tools/xc/lib/libxc_domain.c
new file mode 100644 (file)
index 0000000..93881d1
--- /dev/null
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * libxc_domain.c
+ * 
+ * API for manipulating and obtaining information on domains.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#include "libxc_private.h"
+
+int xc_domain_create(int xc_handle,
+                     unsigned int mem_kb, 
+                     const char *name)
+{
+    int err;
+    dom0_op_t op;
+
+    op.cmd = DOM0_CREATEDOMAIN;
+    op.u.createdomain.memory_kb = mem_kb;
+    strncpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
+    op.u.createdomain.name[MAX_DOMAIN_NAME-1] = '\0';
+
+    err = do_dom0_op(xc_handle, &op);
+
+    return (err < 0) ? err : op.u.createdomain.domain;
+}    
+
+
+int xc_domain_start(int xc_handle,
+                    unsigned int domid)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_STARTDOMAIN;
+    op.u.startdomain.domain = domid;
+    return do_dom0_op(xc_handle, &op);
+}    
+
+
+int xc_domain_stop(int xc_handle, 
+                   unsigned int domid)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_STOPDOMAIN;
+    op.u.stopdomain.domain = domid;
+    return do_dom0_op(xc_handle, &op);
+}    
+
+
+int xc_domain_destroy(int xc_handle,
+                      unsigned int domid, 
+                      int force)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_DESTROYDOMAIN;
+    op.u.destroydomain.domain = domid;
+    op.u.destroydomain.force  = !!force;
+    return do_dom0_op(xc_handle, &op);
+}
+
+int xc_domain_getinfo(int xc_handle,
+                      unsigned int first_domid,
+                      unsigned int max_doms,
+                      xc_dominfo_t *info)
+{
+    unsigned int nr_doms, next_domid = first_domid;
+    dom0_op_t op;
+
+    for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
+    {
+        op.cmd = DOM0_GETDOMAININFO;
+        op.u.getdomaininfo.domain = next_domid;
+        if ( do_dom0_op(xc_handle, &op) < 0 )
+            break;
+        info->domid   = op.u.getdomaininfo.domain;
+        info->cpu     = op.u.getdomaininfo.processor;
+        info->has_cpu = op.u.getdomaininfo.has_cpu;
+        info->stopped = (op.u.getdomaininfo.state == DOMSTATE_STOPPED);
+        info->nr_pages = op.u.getdomaininfo.tot_pages;
+        info->cpu_time = op.u.getdomaininfo.cpu_time;
+        strncpy(info->name, op.u.getdomaininfo.name, XC_DOMINFO_MAXNAME);
+        info->name[XC_DOMINFO_MAXNAME-1] = '\0';
+
+        next_domid = op.u.getdomaininfo.domain + 1;
+    }
+
+    return nr_doms;
+}
diff --git a/tools/xc/lib/libxc_linux_build.c b/tools/xc/lib/libxc_linux_build.c
new file mode 100644 (file)
index 0000000..08966c8
--- /dev/null
@@ -0,0 +1,478 @@
+/******************************************************************************
+ * libxc_linux_build.c
+ */
+
+#include "libxc_private.h"
+#include <zlib.h>
+
+/* This string is written to the head of every guest kernel image. */
+#define GUEST_SIG   "XenoGues"
+#define SIG_LEN    8
+
+#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
+#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
+
+static long get_tot_pages(int xc_handle, int domid)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_GETDOMAININFO;
+    op.u.getdomaininfo.domain = domid;
+    return (do_dom0_op(xc_handle, &op) < 0) ? 
+        -1 : op.u.getdomaininfo.tot_pages;
+}
+
+static int get_pfn_list(int xc_handle,
+                        int domid, 
+                        unsigned long *pfn_buf, 
+                        unsigned long max_pfns)
+{
+    dom0_op_t op;
+    int ret;
+    op.cmd = DOM0_GETMEMLIST;
+    op.u.getmemlist.domain   = domid;
+    op.u.getmemlist.max_pfns = max_pfns;
+    op.u.getmemlist.buffer   = pfn_buf;
+
+    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
+        return -1;
+
+    ret = do_dom0_op(xc_handle, &op);
+
+    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
+
+    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
+}
+
+static int send_pgupdates(int xc_handle, mmu_update_t *updates, int nr_updates)
+{
+    int ret = -1;
+    privcmd_hypercall_t hypercall;
+
+    hypercall.op     = __HYPERVISOR_mmu_update;
+    hypercall.arg[0] = (unsigned long)updates;
+    hypercall.arg[1] = (unsigned long)nr_updates;
+
+    if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 )
+        goto out1;
+
+    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
+        goto out2;
+
+    ret = 0;
+
+ out2: (void)munlock(updates, nr_updates * sizeof(*updates));
+ out1: return ret;
+}
+
+/* Read the kernel header, extracting the image size and load address. */
+static int read_kernel_header(gzFile gfd, long dom_size, 
+                              unsigned long *load_addr)
+{
+    char signature[SIG_LEN];
+
+    gzread(gfd, signature, SIG_LEN);
+    if ( strncmp(signature, GUEST_SIG, SIG_LEN) )
+    {
+        ERROR("Kernel image does not contain required signature");
+        return -1;
+    }
+
+    /* Read the load address which immediately follows the Xeno signature. */
+    gzread(gfd, load_addr, sizeof(unsigned long));
+
+    return 0;
+}
+
+static int copy_to_domain_page(int pm_handle,
+                               unsigned long dst_pfn, 
+                               void *src_page)
+{
+    void *vaddr = map_pfn(pm_handle, dst_pfn);
+    if ( vaddr == NULL )
+        return -1;
+    memcpy(vaddr, src_page, PAGE_SIZE);
+    unmap_pfn(pm_handle, vaddr);
+    return 0;
+}
+
+static int setup_guestos(int xc_handle,
+                         int dom, 
+                         gzFile kernel_gfd, 
+                         int initrd_fd, 
+                         unsigned long tot_pages,
+                         unsigned long *virt_startinfo_addr, 
+                         unsigned long virt_load_addr, 
+                         dom0_builddomain_t *builddomain, 
+                         const char *cmdline,
+                         unsigned long shared_info_frame)
+{
+    l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
+    l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
+    unsigned long *page_array = NULL;
+    mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL;
+    int alloc_index, num_pt_pages;
+    unsigned long l2tab;
+    unsigned long l1tab = 0;
+    unsigned long num_pgt_updates = 0;
+    unsigned long count, pt_start, i, j;
+    unsigned long initrd_addr = 0, initrd_len = 0;
+    start_info_t *start_info;
+    shared_info_t *shared_info;
+    unsigned long ksize;
+    int pm_handle;
+
+    memset(builddomain, 0, sizeof(*builddomain));
+
+    if ( (pm_handle = init_pfn_mapper()) < 0 )
+        goto error_out;
+
+    pgt_updates = malloc((tot_pages + 1024) * 3 * sizeof(mmu_update_t));
+    page_array = malloc(tot_pages * sizeof(unsigned long));
+    pgt_update_arr = pgt_updates;
+    if ( (pgt_update_arr == NULL) || (page_array == NULL) )
+    {
+        PERROR("Could not allocate memory");
+        goto error_out;
+    }
+
+    if ( get_pfn_list(xc_handle, dom, page_array, tot_pages) != tot_pages )
+    {
+        PERROR("Could not get the page frame list");
+        goto error_out;
+    }
+
+    /* Load the guest OS image. Let it take no more than 1/2 memory.*/
+    for ( i = 0; i < ((tot_pages/2)*PAGE_SIZE); i += PAGE_SIZE )
+    {
+        char page[PAGE_SIZE];
+        int size;
+        if ( (size = gzread(kernel_gfd, page, PAGE_SIZE)) == -1 )
+        {
+            PERROR("Error reading kernel image, could not"
+                   " read the whole image.");
+            goto error_out;
+        }
+        if ( size == 0 )
+            goto kernel_copied;
+        copy_to_domain_page(pm_handle, page_array[i>>PAGE_SHIFT], page);
+    }
+    ERROR("Kernel too big to safely fit in domain memory");
+    goto error_out;
+
+ kernel_copied:
+    /* ksize is kernel-image size rounded up to a page boundary. */
+    ksize = i;
+
+    /* Load the initial ramdisk image. */
+    if ( initrd_fd >= 0 )
+    {
+        struct stat stat;
+        unsigned long isize;
+
+        if ( fstat(initrd_fd, &stat) < 0 )
+        {
+            PERROR("Could not stat the initrd image");
+            goto error_out;
+        }
+        isize = stat.st_size;
+        if ( (isize + ksize) > ((tot_pages/2) * PAGE_SIZE) )
+        {
+            ERROR("Kernel/initrd too big to safely fit in domain memory");
+            goto error_out;
+        }
+
+        initrd_addr = virt_load_addr + ksize;
+        initrd_len  = isize;
+
+        for ( j = 0, i = ksize; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
+        {
+            char page[PAGE_SIZE];
+            int size = ((isize-j) < PAGE_SIZE) ? (isize-j) : PAGE_SIZE;
+            if ( read(initrd_fd, page, size) != size )
+            {
+                PERROR("Error reading initrd image, could not"
+                       " read the whole image.");
+                goto error_out;
+            } 
+            copy_to_domain_page(pm_handle, page_array[i>>PAGE_SHIFT], page);
+        }
+    }
+
+    alloc_index = tot_pages - 1;
+
+    /* Count bottom-level PTs, rounding up. */
+    num_pt_pages = (l1_table_offset(virt_load_addr) + tot_pages + 1023) / 1024;
+
+    /* We must also count the page directory. */
+    num_pt_pages++;
+
+    /* Index of first PT page. */
+    pt_start = tot_pages - num_pt_pages;
+
+    /*
+     * First allocate page for page dir. Allocation goes backwards from the end
+     * of the allocated physical address space.
+     */
+    l2tab = page_array[alloc_index] << PAGE_SHIFT;
+    alloc_index--;
+    builddomain->ctxt.pt_base = l2tab;
+
+    /*
+     * Pin down l2tab addr as page dir page - causes hypervisor to provide
+     * correct protection for the page
+     */ 
+    pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND;
+    pgt_updates->val = MMUEXT_PIN_L2_TABLE;
+    pgt_updates++;
+    num_pgt_updates++;
+
+    /* Initialise the page tables. */
+    if ( (vl2tab = map_pfn(pm_handle, l2tab >> PAGE_SHIFT)) == NULL )
+        goto error_out;
+    memset(vl2tab, 0, PAGE_SIZE);
+    vl2e = vl2tab + l2_table_offset(virt_load_addr);
+    for ( count = 0; count < tot_pages; count++ )
+    {    
+        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) 
+        {
+            l1tab = page_array[alloc_index] << PAGE_SHIFT;
+            if ( (vl1tab = map_pfn(pm_handle, l1tab >> PAGE_SHIFT)) == NULL )
+                goto error_out;
+            memset(vl1tab, 0, PAGE_SIZE);
+            alloc_index--;
+               
+            vl1e = vl1tab + l1_table_offset(virt_load_addr + 
+                                            (count << PAGE_SHIFT));
+
+            /* make apropriate entry in the page directory */
+            pgt_updates->ptr = (unsigned long)vl2e;
+            pgt_updates->val = l1tab | L2_PROT;
+            pgt_updates++;
+            num_pgt_updates++;
+            vl2e++;
+        }
+
+        if ( count < pt_start )
+        {
+            pgt_updates->ptr = (unsigned long)vl1e;
+            pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT;
+            pgt_updates++;
+            num_pgt_updates++;
+            vl1e++;
+        }
+        else
+        {
+            pgt_updates->ptr = (unsigned long)vl1e;
+            pgt_updates->val = 
+                ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
+            pgt_updates++;
+            num_pgt_updates++;
+            vl1e++;
+        }
+
+        pgt_updates->ptr = 
+            (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+        pgt_updates->val = count;
+        pgt_updates++;
+        num_pgt_updates++;
+    }
+
+    *virt_startinfo_addr =
+        virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
+
+    start_info = map_pfn(pm_handle, page_array[alloc_index-1]);
+    memset(start_info, 0, sizeof(*start_info));
+    start_info->pt_base     = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
+    start_info->mod_start   = initrd_addr;
+    start_info->mod_len     = initrd_len;
+    start_info->nr_pages    = tot_pages;
+    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
+    start_info->dom_id      = dom;
+    start_info->flags       = 0;
+    strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN);
+    start_info->cmd_line[MAX_CMD_LEN-1] = '\0';
+
+    unmap_pfn(pm_handle, start_info);
+
+    /* shared_info page starts its life empty. */
+    shared_info = map_pfn(pm_handle, shared_info_frame);
+    memset(shared_info, 0, PAGE_SIZE);
+    unmap_pfn(pm_handle, shared_info);
+
+    /* Send the page update requests down to the hypervisor. */
+    if ( send_pgupdates(xc_handle, pgt_update_arr, num_pgt_updates) < 0 )
+        goto error_out;
+
+    free(page_array);
+    free(pgt_update_arr);
+    return 0;
+
+ error_out:
+    if ( pm_handle >= 0 )
+        (void)close_pfn_mapper(pm_handle);
+    if ( page_array == NULL )
+        free(page_array);
+    if ( pgt_update_arr == NULL )
+        free(pgt_update_arr);
+    return -1;
+}
+
+int xc_domain_build(int xc_handle,
+                    unsigned int domid,
+                    const char *image_name,
+                    const char *ramdisk_name,
+                    const char *cmdline)
+{
+    dom0_op_t launch_op, op;
+    unsigned long load_addr;
+    long tot_pages;
+    int kernel_fd, initrd_fd = -1;
+    gzFile kernel_gfd;
+    int rc, i;
+    full_execution_context_t *ctxt;
+    unsigned long virt_startinfo_addr;
+
+    if ( (tot_pages = get_tot_pages(xc_handle, domid)) < 0 )
+    {
+        PERROR("Could not find total pages for domain");
+        return 1;
+    }
+
+    kernel_fd = open(image_name, O_RDONLY);
+    if ( kernel_fd < 0 )
+    {
+        PERROR("Could not open kernel image");
+        return 1;
+    }
+
+    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
+    {
+        PERROR("Could not allocate decompression state for state file");
+        close(kernel_fd);
+        return 1;
+    }
+
+    rc = read_kernel_header(kernel_gfd,
+                            tot_pages << (PAGE_SHIFT - 10), 
+                            &load_addr);
+    if ( rc < 0 )
+        goto error_out;
+    
+    if ( (load_addr & (PAGE_SIZE-1)) != 0 )
+    {
+        ERROR("We can only deal with page-aligned load addresses");
+        goto error_out;
+    }
+
+    if ( (load_addr + (tot_pages << PAGE_SHIFT)) > HYPERVISOR_VIRT_START )
+    {
+        ERROR("Cannot map all domain memory without hitting Xen space");
+        goto error_out;
+    }
+
+    if ( ramdisk_name != NULL )
+    {
+        initrd_fd = open(ramdisk_name, O_RDONLY);
+        if ( initrd_fd < 0 )
+        {
+            PERROR("Could not open the initial ramdisk image");
+            goto error_out;
+        }
+    }
+
+    op.cmd = DOM0_GETDOMAININFO;
+    op.u.getdomaininfo.domain = domid;
+    if ( (do_dom0_op(xc_handle, &op) < 0) || 
+         (op.u.getdomaininfo.domain != domid) )
+    {
+        PERROR("Could not get info on domain");
+        goto error_out;
+    }
+    if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
+         (op.u.getdomaininfo.ctxt.pt_base != 0) )
+    {
+        ERROR("Domain is already constructed");
+        goto error_out;
+    }
+
+    if ( setup_guestos(xc_handle, domid, kernel_gfd, initrd_fd, tot_pages,
+                       &virt_startinfo_addr,
+                       load_addr, &launch_op.u.builddomain, cmdline,
+                       op.u.getdomaininfo.shared_info_frame) < 0 )
+    {
+        ERROR("Error constructing guest OS");
+        goto error_out;
+    }
+
+    if ( initrd_fd >= 0 )
+        close(initrd_fd);
+    gzclose(kernel_gfd);
+
+    ctxt = &launch_op.u.builddomain.ctxt;
+
+    ctxt->flags = 0;
+
+    /*
+     * Initial register values:
+     *  DS,ES,FS,GS = FLAT_RING1_DS
+     *       CS:EIP = FLAT_RING1_CS:start_pc
+     *       SS:ESP = FLAT_RING1_DS:start_stack
+     *          ESI = start_info
+     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
+     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
+     */
+    ctxt->i386_ctxt.ds = FLAT_RING1_DS;
+    ctxt->i386_ctxt.es = FLAT_RING1_DS;
+    ctxt->i386_ctxt.fs = FLAT_RING1_DS;
+    ctxt->i386_ctxt.gs = FLAT_RING1_DS;
+    ctxt->i386_ctxt.ss = FLAT_RING1_DS;
+    ctxt->i386_ctxt.cs = FLAT_RING1_CS;
+    ctxt->i386_ctxt.eip = load_addr;
+    ctxt->i386_ctxt.esp = virt_startinfo_addr;
+    ctxt->i386_ctxt.esi = virt_startinfo_addr;
+    ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
+
+    /* FPU is set up to default initial state. */
+    memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
+
+    /* Virtual IDT is empty at start-of-day. */
+    for ( i = 0; i < 256; i++ )
+    {
+        ctxt->trap_ctxt[i].vector = i;
+        ctxt->trap_ctxt[i].cs     = FLAT_RING1_CS;
+    }
+    ctxt->fast_trap_idx = 0;
+
+    /* No LDT. */
+    ctxt->ldt_ents = 0;
+    
+    /* Use the default Xen-provided GDT. */
+    ctxt->gdt_ents = 0;
+
+    /* Ring 1 stack is the initial stack. */
+    ctxt->ring1_ss  = FLAT_RING1_DS;
+    ctxt->ring1_esp = virt_startinfo_addr;
+
+    /* No debugging. */
+    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
+
+    /* No callback handlers. */
+    ctxt->event_callback_cs     = FLAT_RING1_CS;
+    ctxt->event_callback_eip    = 0;
+    ctxt->failsafe_callback_cs  = FLAT_RING1_CS;
+    ctxt->failsafe_callback_eip = 0;
+
+    launch_op.u.builddomain.domain   = domid;
+    launch_op.u.builddomain.num_vifs = 1;
+
+    launch_op.cmd = DOM0_BUILDDOMAIN;
+    rc = do_dom0_op(xc_handle, &launch_op);
+    
+    return rc;
+
+ error_out:
+    if ( initrd_fd >= 0 )
+        close(initrd_fd);
+    gzclose(kernel_gfd);
+    return -1;
+}
diff --git a/tools/xc/lib/libxc_linux_restore.c b/tools/xc/lib/libxc_linux_restore.c
new file mode 100644 (file)
index 0000000..e865280
--- /dev/null
@@ -0,0 +1,488 @@
+/******************************************************************************
+ * libxc_linux_restore.c
+ * 
+ * Restore the state of a Xenolinux session.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#include "libxc_private.h"
+#include <asm-xeno/suspend.h>
+#include <zlib.h>
+
+/* This may allow us to create a 'quiet' command-line option, if necessary. */
+#define verbose_printf(_f, _a...) \
+    do {                          \
+        if ( !verbose ) break;    \
+        printf( _f , ## _a );     \
+        fflush(stdout);           \
+    } while ( 0 )
+
+static int get_pfn_list(int xc_handle,
+                        int domain_id, 
+                        unsigned long *pfn_buf, 
+                        unsigned long max_pfns)
+{
+    dom0_op_t op;
+    int ret;
+    op.cmd = DOM0_GETMEMLIST;
+    op.u.getmemlist.domain   = domain_id;
+    op.u.getmemlist.max_pfns = max_pfns;
+    op.u.getmemlist.buffer   = pfn_buf;
+
+    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
+    {
+        PERROR("Could not lock pfn list buffer");
+        return -1;
+    }    
+
+    ret = do_dom0_op(xc_handle, &op);
+
+    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
+
+    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
+}
+
+#define MAX_MMU_UPDATES 1024
+
+static int flush_mmu_updates(int xc_handle,
+                             mmu_update_t *mmu_updates,
+                             int *mmu_update_idx)
+{
+    int err = 0;
+    privcmd_hypercall_t hypercall;
+
+    if ( *mmu_update_idx == 0 )
+        return 0;
+
+    hypercall.op     = __HYPERVISOR_mmu_update;
+    hypercall.arg[0] = (unsigned long)mmu_updates;
+    hypercall.arg[1] = (unsigned long)*mmu_update_idx;
+
+    if ( mlock(mmu_updates, sizeof(mmu_updates)) != 0 )
+    {
+        PERROR("Could not lock pagetable update array");
+        err = 1;
+        goto out;
+    }
+
+    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
+    {
+        ERROR("Failure when submitting mmu updates");
+        err = 1;
+    }
+
+    *mmu_update_idx = 0;
+    
+    (void)munlock(mmu_updates, sizeof(mmu_updates));
+
+ out:
+    return err;
+}
+
+static int add_mmu_update(int xc_handle,
+                          mmu_update_t *mmu_updates,
+                          int *mmu_update_idx,
+                          unsigned long ptr, 
+                          unsigned long val)
+{
+    mmu_updates[*mmu_update_idx].ptr = ptr;
+    mmu_updates[*mmu_update_idx].val = val;
+    if ( ++*mmu_update_idx == MAX_MMU_UPDATES )
+        return flush_mmu_updates(xc_handle, mmu_updates, mmu_update_idx);
+    return 0;
+}
+
+static int checked_read(gzFile fd, void *buf, size_t count)
+{
+    int rc;
+    while ( ((rc = gzread(fd, buf, count)) == -1) && (errno == EINTR) )
+        continue;
+    return rc == count;
+}
+
+int xc_linux_restore(int xc_handle,
+                     const char *state_file,
+                     int verbose)
+{
+    dom0_op_t op;
+    int rc = 1, i, j;
+    unsigned long mfn, pfn, dom = 0;
+    unsigned int prev_pc, this_pc;
+    
+    /* Number of page frames in use by this XenoLinux session. */
+    unsigned long nr_pfns;
+
+    /* The new domain's shared-info frame number. */
+    unsigned long shared_info_frame;
+    unsigned char shared_info[PAGE_SIZE]; /* saved contents from file */
+    
+    /* A copy of the CPU context of the guest. */
+    full_execution_context_t ctxt;
+
+    /* First 16 bytes of the state file must contain 'XenoLinuxSuspend'. */
+    char signature[16];
+    
+    /* A copy of the domain's name. */
+    char name[MAX_DOMAIN_NAME];
+
+    /* A table containg the type of each PFN (/not/ MFN!). */
+    unsigned long *pfn_type = NULL;
+
+    /* A temporary mapping, and a copy, of one frame of guest memory. */
+    unsigned long *ppage, page[1024];
+
+    /* A copy of the pfn-to-mfn table frame list. */
+    unsigned long pfn_to_mfn_frame_list[1024];
+
+    /* A table mapping each PFN to its new MFN. */
+    unsigned long *pfn_to_mfn_table = NULL;
+
+    /* A temporary mapping of the guest's suspend record. */
+    suspend_record_t *p_srec;
+
+    /* The name and descriptor of the file that we are reading from. */
+    int    fd;
+    gzFile gfd;
+
+    mmu_update_t mmu_updates[MAX_MMU_UPDATES];
+    int mmu_update_idx = 0;
+
+    int pm_handle = -1;
+
+    if ( (fd = open(state_file, O_RDONLY)) == -1 )
+    {
+        PERROR("Could not open state file for reading");
+        return 1;
+    }
+
+    if ( (gfd = gzdopen(fd, "rb")) == NULL )
+    {
+        ERROR("Could not allocate decompression state for state file");
+        close(fd);
+        return 1;
+    }
+
+    /* Start writing out the saved-domain record. */
+    if ( !checked_read(gfd, signature, 16) ||
+         (memcmp(signature, "XenoLinuxSuspend", 16) != 0) )
+    {
+        ERROR("Unrecognised state format -- no signature found");
+        goto out;
+    }
+
+    if ( !checked_read(gfd, name,                  sizeof(name)) ||
+         !checked_read(gfd, &nr_pfns,              sizeof(unsigned long)) ||
+         !checked_read(gfd, &ctxt,                 sizeof(ctxt)) ||
+         !checked_read(gfd, shared_info,           PAGE_SIZE) ||
+         !checked_read(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) )
+    {
+        ERROR("Error when reading from state file");
+        goto out;
+    }
+
+    for ( i = 0; i < MAX_DOMAIN_NAME; i++ )
+    {
+        if ( name[i] == '\0' ) break;
+        if ( name[i] & 0x80 )
+        {
+            ERROR("Random characters in domain name");
+            goto out;
+        }
+    }
+    name[MAX_DOMAIN_NAME-1] = '\0';
+
+    if ( nr_pfns > 1024*1024 )
+    {
+        ERROR("Invalid state file -- pfn count out of range");
+        goto out;
+    }
+
+    /* We want zeroed memory so use calloc rather than malloc. */
+    pfn_to_mfn_table = calloc(1, 4 * nr_pfns);
+    pfn_type         = calloc(1, 4 * nr_pfns);    
+
+    if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) )
+    {
+        errno = ENOMEM;
+        goto out;
+    }
+
+    if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) )
+    {
+        ERROR("Error when reading from state file");
+        goto out;
+    }
+
+    /* Create a new domain of the appropriate size, and find it's dom_id. */
+    op.cmd = DOM0_CREATEDOMAIN;
+    op.u.createdomain.memory_kb = nr_pfns * (PAGE_SIZE / 1024);
+    memcpy(op.u.createdomain.name, name, MAX_DOMAIN_NAME);
+    if ( do_dom0_op(xc_handle, &op) < 0 )
+    {
+        ERROR("Could not create new domain");
+        goto out;
+    }
+    dom = op.u.createdomain.domain;
+
+    /* Get the domain's shared-info frame. */
+    op.cmd = DOM0_GETDOMAININFO;
+    op.u.getdomaininfo.domain = dom;
+    if ( do_dom0_op(xc_handle, &op) < 0 )
+    {
+        ERROR("Could not get information on new domain");
+        goto out;
+    }
+    shared_info_frame = op.u.getdomaininfo.shared_info_frame;
+
+    if ( (pm_handle = init_pfn_mapper()) < 0 )
+        goto out;
+
+    /* Copy saved contents of shared-info page. No checking needed. */
+    ppage = map_pfn(pm_handle, shared_info_frame);
+    memcpy(ppage, shared_info, PAGE_SIZE);
+    unmap_pfn(pm_handle, ppage);
+
+    /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
+    if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns )
+    {
+        ERROR("Did not read correct number of frame numbers for new dom");
+        goto out;
+    }
+
+    verbose_printf("Reloading memory pages:   0%%");
+
+    /*
+     * Now simply read each saved frame into its new machine frame.
+     * We uncanonicalise page tables as we go.
+     */
+    prev_pc = 0;
+    for ( i = 0; i < nr_pfns; i++ )
+    {
+        this_pc = (i * 100) / nr_pfns;
+        if ( (this_pc - prev_pc) >= 5 )
+        {
+            verbose_printf("\b\b\b\b%3d%%", this_pc);
+            prev_pc = this_pc;
+        }
+
+        mfn = pfn_to_mfn_table[i];
+
+        if ( !checked_read(gfd, page, PAGE_SIZE) )
+        {
+            ERROR("Error when reading from state file");
+            goto out;
+        }
+
+        ppage = map_pfn(pm_handle, mfn);
+        switch ( pfn_type[i] )
+        {
+        case L1TAB:
+            memset(ppage, 0, PAGE_SIZE);
+            if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
+                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
+                                MMUEXT_PIN_L1_TABLE) )
+                goto out;
+            for ( j = 0; j < 1024; j++ )
+            {
+                if ( page[j] & _PAGE_PRESENT )
+                {
+                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
+                    {
+                        ERROR("Frame number in page table is out of range");
+                        goto out;
+                    }
+                    if ( (pfn_type[pfn] != NONE) && (page[j] & _PAGE_RW) )
+                    {
+                        ERROR("Write access requested for a restricted frame");
+                        goto out;
+                    }
+                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
+                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
+                }
+                if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
+                                    (unsigned long)&ppage[j], page[j]) )
+                    goto out;
+            }
+            break;
+        case L2TAB:
+            memset(ppage, 0, PAGE_SIZE);
+            if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
+                                (mfn<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND,
+                                MMUEXT_PIN_L2_TABLE) )
+                goto out;
+            for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ )
+            {
+                if ( page[j] & _PAGE_PRESENT )
+                {
+                    if ( (pfn = page[j] >> PAGE_SHIFT) >= nr_pfns )
+                    {
+                        ERROR("Frame number in page table is out of range");
+                        goto out;
+                    }
+                    if ( pfn_type[pfn] != L1TAB )
+                    {
+                        ERROR("Page table mistyping");
+                        goto out;
+                    }
+                    /* Haven't reached the L1 table yet. Ensure it is safe! */
+                    if ( pfn > i )
+                    {
+                        unsigned long **l1 = map_pfn(pm_handle, 
+                                                     pfn_to_mfn_table[pfn]);
+                        memset(l1, 0, PAGE_SIZE);
+                        unmap_pfn(pm_handle, l1);
+                    }
+                    page[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE);
+                    page[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
+                }
+                if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
+                                    (unsigned long)&ppage[j], page[j]) )
+                    goto out;
+            }
+            break;
+        default:
+            memcpy(ppage, page, PAGE_SIZE);
+            break;
+        }
+        /* NB. Must flush before unmapping page, as pass VAs to Xen. */
+        if ( flush_mmu_updates(xc_handle, mmu_updates, &mmu_update_idx) )
+            goto out;
+        unmap_pfn(pm_handle, ppage);
+
+        if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx,
+                            (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) )
+            goto out;
+    }
+
+    if ( flush_mmu_updates(xc_handle, mmu_updates, &mmu_update_idx) )
+        goto out;
+
+    verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n");
+
+    /* Uncanonicalise the suspend-record frame number and poke resume rec. */
+    pfn = ctxt.i386_ctxt.esi;
+    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
+    {
+        ERROR("Suspend record frame number is bad");
+        goto out;
+    }
+    ctxt.i386_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
+    p_srec = map_pfn(pm_handle, mfn);
+    p_srec->resume_info.nr_pages    = nr_pfns;
+    p_srec->resume_info.shared_info = shared_info_frame << PAGE_SHIFT;
+    p_srec->resume_info.dom_id      = dom;
+    p_srec->resume_info.flags       = 0;
+    unmap_pfn(pm_handle, p_srec);
+
+    /* Uncanonicalise each GDT frame number. */
+    if ( ctxt.gdt_ents > 8192 )
+    {
+        ERROR("GDT entry count out of range");
+        goto out;
+    }
+    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
+    {
+        pfn = ctxt.gdt_frames[i];
+        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
+        {
+            ERROR("GDT frame number is bad");
+            goto out;
+        }
+        ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
+    }
+
+    /* Uncanonicalise the page table base pointer. */
+    pfn = ctxt.pt_base >> PAGE_SHIFT;
+    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) )
+    {
+        ERROR("PT base is bad");
+        goto out;
+    }
+    ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
+
+    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
+    for ( i = 0; i < nr_pfns; i += 1024 )
+    {
+        unsigned long copy_size = (nr_pfns - i) * sizeof(unsigned long);
+        if ( copy_size > PAGE_SIZE ) copy_size = PAGE_SIZE;
+        pfn = pfn_to_mfn_frame_list[i/1024];
+        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NONE) )
+        {
+            ERROR("PFN-to-MFN frame number is bad");
+            goto out;
+        }
+        ppage = map_pfn(pm_handle, pfn_to_mfn_table[pfn]);
+        memcpy(ppage, &pfn_to_mfn_table[i], copy_size);        
+        unmap_pfn(pm_handle, ppage);
+    }
+
+    /*
+     * Safety checking of saved context:
+     *  1. i386_ctxt is fine, as Xen checks that on context switch.
+     *  2. i387_ctxt is fine, as it can't hurt Xen.
+     *  3. trap_ctxt needs the code selectors checked.
+     *  4. fast_trap_idx is checked by Xen.
+     *  5. ldt base must be page-aligned, no more than 8192 ents, ...
+     *  6. gdt already done, and further checking is done by Xen.
+     *  7. check that ring1_ss is safe.
+     *  8. pt_base is already done.
+     *  9. debugregs are checked by Xen.
+     *  10. callback code selectors need checking.
+     */
+    for ( i = 0; i < 256; i++ )
+    {
+        ctxt.trap_ctxt[i].vector = i;
+        if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
+            ctxt.trap_ctxt[i].cs = FLAT_RING1_CS;
+    }
+    if ( (ctxt.ring1_ss & 3) == 0 )
+        ctxt.ring1_ss = FLAT_RING1_DS;
+    if ( (ctxt.event_callback_cs & 3) == 0 )
+        ctxt.event_callback_cs = FLAT_RING1_CS;
+    if ( (ctxt.failsafe_callback_cs & 3) == 0 )
+        ctxt.failsafe_callback_cs = FLAT_RING1_CS;
+    if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
+         (ctxt.ldt_ents > 8192) ||
+         (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
+         ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
+    {
+        ERROR("Bad LDT base or size");
+        goto out;
+    }
+
+    op.cmd = DOM0_BUILDDOMAIN;
+    op.u.builddomain.domain   = dom;
+    op.u.builddomain.num_vifs = 1;
+    memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt));
+    rc = do_dom0_op(xc_handle, &op);
+
+ out:
+    if ( rc != 0 )
+    {
+        if ( dom != 0 )
+        {
+            op.cmd = DOM0_DESTROYDOMAIN;
+            op.u.destroydomain.domain = dom;
+            op.u.destroydomain.force  = 1;
+            (void)do_dom0_op(xc_handle, &op);
+        }
+    }
+    else
+    {
+        /* Success: print the domain id. */
+        verbose_printf("DOM=%ld\n", dom);
+    }
+
+    if ( pm_handle >= 0 )
+        (void)close_pfn_mapper(pm_handle);
+
+    if ( pfn_to_mfn_table != NULL )
+        free(pfn_to_mfn_table);
+    if ( pfn_type != NULL )
+        free(pfn_type);
+
+    gzclose(gfd);
+
+    return (rc == 0) ? dom : rc;
+}
diff --git a/tools/xc/lib/libxc_linux_save.c b/tools/xc/lib/libxc_linux_save.c
new file mode 100644 (file)
index 0000000..0986c96
--- /dev/null
@@ -0,0 +1,392 @@
+/******************************************************************************
+ * libxc_linux_save.c
+ * 
+ * Save the state of a running Xenolinux session.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#include "libxc_private.h"
+#include <asm-xeno/suspend.h>
+#include <zlib.h>
+
+/* This may allow us to create a 'quiet' command-line option, if necessary. */
+#define verbose_printf(_f, _a...) \
+    do {                          \
+        if ( !verbose ) break;    \
+        printf( _f , ## _a );     \
+        fflush(stdout);           \
+    } while ( 0 )
+
+/*
+ * Returns TRUE if the given machine frame number has a unique mapping
+ * in the guest's pseudophysical map.
+ */
+#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \
+    (((_mfn) < (1024*1024)) &&          \
+     (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn)))
+
+/* Returns TRUE if MFN is successfully converted to a PFN. */
+#define translate_mfn_to_pfn(_pmfn)         \
+({                                          \
+    unsigned long mfn = *(_pmfn);           \
+    int _res = 1;                           \
+    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )   \
+        _res = 0;                           \
+    else                                    \
+        *(_pmfn) = mfn_to_pfn_table[mfn];   \
+    _res;                                   \
+})
+
+static int check_pfn_ownership(int xc_handle, 
+                               unsigned long mfn, 
+                               unsigned int dom)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_GETPAGEFRAMEINFO;
+    op.u.getpageframeinfo.pfn = mfn;
+    if ( (do_dom0_op(xc_handle, &op) < 0) || 
+         (op.u.getpageframeinfo.domain != dom) )
+        return 0;
+    return 1;
+}
+
+#define GETPFN_ERR (~0U)
+static unsigned int get_pfn_type(int xc_handle, unsigned long mfn)
+{
+    dom0_op_t op;
+    op.cmd = DOM0_GETPAGEFRAMEINFO;
+    op.u.getpageframeinfo.pfn = mfn;
+    if ( do_dom0_op(xc_handle, &op) < 0 )
+    {
+        PERROR("Unexpected failure when getting page frame info!");
+        return GETPFN_ERR;
+    }
+    return op.u.getpageframeinfo.type;
+}
+
+static int checked_write(gzFile fd, void *buf, size_t count)
+{
+    int rc;
+    while ( ((rc = gzwrite(fd, buf, count)) == -1) && (errno = EINTR) )
+        continue;
+    return rc == count;
+}
+
+int xc_linux_save(int xc_handle,
+                  unsigned int domid, 
+                  const char *state_file, 
+                  int verbose)
+{
+    dom0_op_t op;
+    int rc = 1, i, j;
+    unsigned long mfn;
+    unsigned int prev_pc, this_pc;
+
+    /* Remember if we stopped the guest, so we can restart it on exit. */
+    int we_stopped_it = 0;
+
+    /* The new domain's shared-info frame number. */
+    unsigned long shared_info_frame;
+    
+    /* A copy of the CPU context of the guest. */
+    full_execution_context_t ctxt;
+
+    /* A copy of the domain's name. */
+    char name[MAX_DOMAIN_NAME];
+
+    /* A table containg the type of each PFN (/not/ MFN!). */
+    unsigned long *pfn_type = NULL;
+
+    /* A temporary mapping, and a copy, of one frame of guest memory. */
+    unsigned long *ppage, page[1024];
+
+    /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */
+    unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024];
+    /* A temporary mapping of one frame in the above list. */
+    unsigned long *pfn_to_mfn_frame;
+
+    /* A table mapping each PFN to its current MFN. */
+    unsigned long *pfn_to_mfn_table = NULL;
+    /* A table mapping each current MFN to its canonical PFN. */
+    unsigned long *mfn_to_pfn_table = NULL;
+    
+    /* A temporary mapping, and a copy, of the guest's suspend record. */
+    suspend_record_t *p_srec, srec;
+
+    /* The name and descriptor of the file that we are writing to. */
+    int    fd;
+    gzFile gfd;
+
+    int pm_handle = -1;
+
+    if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
+    {
+        PERROR("Could not open file for writing");
+        return 1;
+    }
+
+    /*
+     * Compression rate 1: we want speed over compression. We're mainly going
+     * for those zero pages, after all.
+     */
+    if ( (gfd = gzdopen(fd, "wb1")) == NULL )
+    {
+        ERROR("Could not allocate compression state for state file");
+        close(fd);
+        return 1;
+    }
+
+    /* Ensure that the domain exists, and that it is stopped. */
+    for ( ; ; )
+    {
+        op.cmd = DOM0_GETDOMAININFO;
+        op.u.getdomaininfo.domain = domid;
+        if ( (do_dom0_op(xc_handle, &op) < 0) || 
+             (op.u.getdomaininfo.domain != domid) )
+        {
+            PERROR("Could not get info on domain");
+            goto out;
+        }
+
+        memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt));
+        memcpy(name, op.u.getdomaininfo.name, sizeof(name));
+        shared_info_frame = op.u.getdomaininfo.shared_info_frame;
+
+        if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
+            break;
+
+        we_stopped_it = 1;
+
+        op.cmd = DOM0_STOPDOMAIN;
+        op.u.stopdomain.domain = domid;
+        (void)do_dom0_op(xc_handle, &op);
+
+        sleep(1);
+    }
+
+    /* A cheesy test to see whether the domain contains valid state. */
+    if ( ctxt.pt_base == 0 )
+    {
+        ERROR("Domain is not in a valid Xenolinux state");
+        goto out;
+    }
+
+    if ( (pm_handle = init_pfn_mapper()) < 0 )
+        goto out;
+
+    /* Is the suspend-record MFN actually valid for this domain? */
+    if ( !check_pfn_ownership(xc_handle, ctxt.i386_ctxt.esi, domid) )
+    {
+        ERROR("Invalid state record pointer");
+        goto out;
+    }
+
+    /* If the suspend-record MFN is okay then grab a copy of it to @srec. */
+    p_srec = map_pfn(pm_handle, ctxt.i386_ctxt.esi);
+    memcpy(&srec, p_srec, sizeof(srec));
+    unmap_pfn(pm_handle, p_srec);
+
+    if ( srec.nr_pfns > 1024*1024 )
+    {
+        ERROR("Invalid state record -- pfn count out of range");
+        goto out;
+    }
+
+    if ( !check_pfn_ownership(xc_handle, srec.pfn_to_mfn_frame_list, domid) )
+    {
+        ERROR("Invalid pfn-to-mfn frame list pointer");
+        goto out;
+    }
+
+    /* Grab a copy of the pfn-to-mfn table frame list. */
+    p_pfn_to_mfn_frame_list = map_pfn(pm_handle, srec.pfn_to_mfn_frame_list);
+    memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE);
+    unmap_pfn(pm_handle, p_pfn_to_mfn_frame_list);
+
+    /* We want zeroed memory so use calloc rather than malloc. */
+    mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024);
+    pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns);
+    pfn_type         = calloc(1, 4 * srec.nr_pfns);
+
+    if ( (mfn_to_pfn_table == NULL) ||
+         (pfn_to_mfn_table == NULL) ||
+         (pfn_type == NULL) )
+    {
+        errno = ENOMEM;
+        goto out;
+    }
+
+
+    /*
+     * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
+     * loop we have each MFN mapped at most once. Note that there may be MFNs
+     * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
+     */
+    pfn_to_mfn_frame = NULL;
+    for ( i = 0; i < srec.nr_pfns; i++ )
+    {
+        /* Each frameful of table frames must be checked & mapped on demand. */
+        if ( (i & 1023) == 0 )
+        {
+            mfn = pfn_to_mfn_frame_list[i/1024];
+            if ( !check_pfn_ownership(xc_handle, mfn, domid) )
+            {
+                ERROR("Invalid frame number if pfn-to-mfn frame list");
+                goto out;
+            }
+            if ( pfn_to_mfn_frame != NULL )
+                unmap_pfn(pm_handle, pfn_to_mfn_frame);
+            pfn_to_mfn_frame = map_pfn(pm_handle, mfn);
+        }
+        
+        mfn = pfn_to_mfn_frame[i & 1023];
+
+        if ( !check_pfn_ownership(xc_handle, mfn, domid) )
+        {
+            ERROR("Invalid frame specified with pfn-to-mfn table");
+            goto out;
+        }
+
+        /* Did we map this MFN already? That would be invalid! */
+        if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
+        {
+            ERROR("A machine frame appears twice in pseudophys space");
+            goto out;
+        }
+
+        pfn_to_mfn_table[i] = mfn;
+        mfn_to_pfn_table[mfn] = i;
+
+        /* Query page type by MFN, but store it by PFN. */
+        if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn)) == GETPFN_ERR )
+            goto out;
+    }
+
+    /* Canonicalise the suspend-record frame number. */
+    if ( !translate_mfn_to_pfn(&ctxt.i386_ctxt.esi) )
+    {
+        ERROR("State record is not in range of pseudophys map");
+        goto out;
+    }
+
+    /* Canonicalise each GDT frame number. */
+    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
+    {
+        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) )
+        {
+            ERROR("GDT frame is not in range of pseudophys map");
+            goto out;
+        }
+    }
+
+    /* Canonicalise the page table base pointer. */
+    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) )
+    {
+        ERROR("PT base is not in range of pseudophys map");
+        goto out;
+    }
+    ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
+
+    /* Canonicalise the pfn-to-mfn table frame-number list. */
+    for ( i = 0; i < srec.nr_pfns; i += 1024 )
+    {
+        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
+        {
+            ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
+            goto out;
+        }
+    }
+
+    /* Start writing out the saved-domain record. */
+    ppage = map_pfn(pm_handle, shared_info_frame);
+    if ( !checked_write(gfd, "XenoLinuxSuspend",    16) ||
+         !checked_write(gfd, name,                  sizeof(name)) ||
+         !checked_write(gfd, &srec.nr_pfns,         sizeof(unsigned long)) ||
+         !checked_write(gfd, &ctxt,                 sizeof(ctxt)) ||
+         !checked_write(gfd, ppage,                 PAGE_SIZE) ||
+         !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ||
+         !checked_write(gfd, pfn_type,              4 * srec.nr_pfns) )
+    {
+        ERROR("Error when writing to state file");
+        goto out;
+    }
+    unmap_pfn(pm_handle, ppage);
+
+    verbose_printf("Saving memory pages:   0%%");
+
+    /* Now write out each data page, canonicalising page tables as we go... */
+    prev_pc = 0;
+    for ( i = 0; i < srec.nr_pfns; i++ )
+    {
+        this_pc = (i * 100) / srec.nr_pfns;
+        if ( (this_pc - prev_pc) >= 5 )
+        {
+            verbose_printf("\b\b\b\b%3d%%", this_pc);
+            prev_pc = this_pc;
+        }
+
+        mfn = pfn_to_mfn_table[i];
+
+        ppage = map_pfn(pm_handle, mfn);
+        memcpy(page, ppage, PAGE_SIZE);
+        unmap_pfn(pm_handle, ppage);
+
+        if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
+        {
+            for ( j = 0; 
+                  j < ((pfn_type[i] == L2TAB) ? 
+                       (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
+                  j++ )
+            {
+                if ( !(page[j] & _PAGE_PRESENT) ) continue;
+                mfn = page[j] >> PAGE_SHIFT;
+                if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
+                {
+                    ERROR("Frame number in pagetable page is invalid");
+                    goto out;
+                }
+                page[j] &= PAGE_SIZE - 1;
+                page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
+            }
+        }
+
+        if ( !checked_write(gfd, page, PAGE_SIZE) )
+        {
+            ERROR("Error when writing to state file");
+            goto out;
+        }
+    }
+
+    verbose_printf("\b\b\b\b100%%\nMemory saved.\n");
+
+    /* Success! */
+    rc = 0;
+
+ out:
+    /* Restart the domain if we had to stop it to save its state. */
+    if ( we_stopped_it )
+    {
+        op.cmd = DOM0_STARTDOMAIN;
+        op.u.startdomain.domain = domid;
+        (void)do_dom0_op(xc_handle, &op);
+    }
+
+    gzclose(gfd);
+
+    if ( pm_handle >= 0 )
+        (void)close_pfn_mapper(pm_handle);
+
+    if ( pfn_to_mfn_table != NULL )
+        free(pfn_to_mfn_table);
+    if ( mfn_to_pfn_table != NULL )
+        free(mfn_to_pfn_table);
+    if ( pfn_type != NULL )
+        free(pfn_type);
+
+    /* On error, make sure the file is deleted. */
+    if ( rc != 0 )
+        unlink(state_file);
+    
+    return !!rc;
+}
diff --git a/tools/xc/lib/libxc_misc.c b/tools/xc/lib/libxc_misc.c
new file mode 100644 (file)
index 0000000..297f40f
--- /dev/null
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * libxc_misc.c
+ * 
+ * Miscellaneous control interface functions.
+ */
+
+#include "libxc_private.h"
+
+int xc_interface_open(void)
+{
+    return open("/proc/xeno/privcmd", O_RDWR);
+}
+
+int xc_interface_close(int xc_handle)
+{
+    return close(xc_handle);
+}
+
+
+#define CONSOLE_RING_CLEAR     1
+
+int xc_readconsolering(int xc_handle,
+                       char *str, 
+                       unsigned int max_chars, 
+                       int clear)
+{
+    int ret;
+    dom0_op_t op;
+
+    op.cmd = DOM0_READCONSOLE;
+    op.u.readconsole.str = (unsigned long)str;
+    op.u.readconsole.count = max_chars;
+    op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
+
+    if ( (ret = do_dom0_op(xc_handle, &op)) > 0 )
+        str[ret] = '\0';
+
+    return ret;
+}    
+
diff --git a/tools/xc/lib/libxc_private.c b/tools/xc/lib/libxc_private.c
new file mode 100644 (file)
index 0000000..c93bed8
--- /dev/null
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * libxc_private.c
+ * 
+ * Helper functions for the rest of the library.
+ */
+
+#include "libxc_private.h"
+
+int init_pfn_mapper(void)
+{
+    return open("/dev/mem", O_RDWR);
+}
+
+int close_pfn_mapper(int pm_handle)
+{
+    return close(pm_handle);
+}
+
+void *map_pfn(int pm_handle, unsigned long pfn)
+{
+    void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
+                       MAP_SHARED, pm_handle, pfn << PAGE_SHIFT);
+    if ( vaddr == MAP_FAILED )
+        return NULL;
+    return vaddr;
+}
+
+void unmap_pfn(int pm_handle, void *vaddr)
+{
+    (void)munmap(vaddr, PAGE_SIZE);
+}
diff --git a/tools/xc/lib/libxc_private.h b/tools/xc/lib/libxc_private.h
new file mode 100644 (file)
index 0000000..3eb412d
--- /dev/null
@@ -0,0 +1,169 @@
+
+#ifndef __LIBXC_PRIVATE_H__
+#define __LIBXC_PRIVATE_H__
+
+typedef unsigned char      u8;
+typedef unsigned short     u16;
+typedef unsigned long      u32;
+typedef unsigned long long u64;
+typedef signed char        s8;
+typedef signed short       s16;
+typedef signed long        s32;
+typedef signed long long   s64;
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+
+#include "xc.h"
+
+#include <asm-xeno/proc_cmd.h>
+#include <hypervisor-ifs/hypervisor-if.h>
+#include <hypervisor-ifs/dom0_ops.h>
+#include <hypervisor-ifs/vbd.h>
+
+#define _PAGE_PRESENT   0x001
+#define _PAGE_RW        0x002
+#define _PAGE_USER      0x004
+#define _PAGE_PWT       0x008
+#define _PAGE_PCD       0x010
+#define _PAGE_ACCESSED  0x020
+#define _PAGE_DIRTY     0x040
+#define _PAGE_PAT       0x080
+#define _PAGE_PSE       0x080
+#define _PAGE_GLOBAL    0x100
+
+
+#define L1_PAGETABLE_SHIFT       12
+#define L2_PAGETABLE_SHIFT       22
+#define ENTRIES_PER_L1_PAGETABLE 1024
+#define ENTRIES_PER_L2_PAGETABLE 1024
+#define PAGE_SHIFT              L1_PAGETABLE_SHIFT
+#define PAGE_SIZE               (1UL << PAGE_SHIFT)
+#define PAGE_MASK               (~(PAGE_SIZE-1))
+
+typedef struct { unsigned long l1_lo; } l1_pgentry_t;
+typedef struct { unsigned long l2_lo; } l2_pgentry_t;
+
+#define l1_table_offset(_a) \
+          (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
+#define l2_table_offset(_a) \
+          ((_a) >> L2_PAGETABLE_SHIFT)
+
+#define ERROR(_m)  \
+    fprintf(stderr, "ERROR: %s\n", (_m))
+
+#define PERROR(_m) \
+    fprintf(stderr, "ERROR: %s (%d = %s)\n", (_m), errno, strerror(errno))
+
+static inline int do_privcmd(int xc_handle,
+                             unsigned int cmd, 
+                             unsigned long data)
+{
+    return ioctl(xc_handle, cmd, data);
+}
+
+static inline int do_xen_hypercall(int xc_handle,
+                                   privcmd_hypercall_t *hypercall)
+{
+    return do_privcmd(xc_handle,
+                      IOCTL_PRIVCMD_HYPERCALL, 
+                      (unsigned long)hypercall);
+}
+
+static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
+{
+    int ret = -1;
+    privcmd_hypercall_t hypercall;
+
+    op->interface_version = DOM0_INTERFACE_VERSION;
+
+    hypercall.op     = __HYPERVISOR_dom0_op;
+    hypercall.arg[0] = (unsigned long)op;
+
+    if ( mlock(op, sizeof(*op)) != 0 )
+    {
+        PERROR("Could not lock memory for Xen hypercall");
+        goto out1;
+    }
+
+    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
+    {
+        if ( errno == EACCES )
+            fprintf(stderr, "Dom0 operation failed -- need to"
+                    " rebuild the user-space tool set?\n");
+        goto out2;
+    }
+
+    ret = 0;
+
+ out2: (void)munlock(op, sizeof(*op));
+ out1: return ret;
+}
+
+static inline int do_network_op(int xc_handle, network_op_t *op)
+{
+    int ret = -1;
+    privcmd_hypercall_t hypercall;
+
+    hypercall.op     = __HYPERVISOR_network_op;
+    hypercall.arg[0] = (unsigned long)op;
+
+    if ( mlock(op, sizeof(*op)) != 0 )
+    {
+        PERROR("Could not lock memory for Xen hypercall");
+        goto out1;
+    }
+
+    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
+        goto out2;
+
+    ret = 0;
+
+ out2: (void)munlock(op, sizeof(*op));
+ out1: return ret;
+}
+
+
+static inline int do_block_io_op(int xc_handle, block_io_op_t *op)
+{
+    int ret = -1;
+    privcmd_hypercall_t hypercall;
+
+    hypercall.op     = __HYPERVISOR_block_io_op;
+    hypercall.arg[0] = (unsigned long)op;
+
+    if ( mlock(op, sizeof(*op)) != 0 )
+    {
+        PERROR("Could not lock memory for Xen hypercall");
+        goto out1;
+    }
+
+    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
+        goto out2;
+
+    ret = 0;
+
+ out2: (void)munlock(op, sizeof(*op));
+ out1: return ret;
+}
+
+/*
+ * PFN mapping.
+ */
+int init_pfn_mapper(void);
+int close_pfn_mapper(int pm_handle);
+void *map_pfn(int pm_handle, unsigned long pfn);
+void unmap_pfn(int pm_handle, void *vaddr);
+
+#endif /* __LIBXC_PRIVATE_H__ */
diff --git a/tools/xc/lib/libxc_vbd.c b/tools/xc/lib/libxc_vbd.c
new file mode 100644 (file)
index 0000000..64e21f7
--- /dev/null
@@ -0,0 +1,124 @@
+/******************************************************************************
+ * libxc_vbd.c
+ * 
+ * API for manipulating and accessing per-domain virtual block devices.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#define _GNU_SOURCE
+#include "libxc_private.h"
+
+int xc_vbd_create(int xc_handle,
+                  unsigned int domid, 
+                  unsigned short vbdid, 
+                  int writeable)
+{
+    block_io_op_t op; 
+    op.cmd = BLOCK_IO_OP_VBD_CREATE; 
+    op.u.create_params.domain  = domid;
+    op.u.create_params.vdevice = vbdid;
+    op.u.create_params.mode    = VBD_MODE_R | (writeable ? VBD_MODE_W : 0);
+    return do_block_io_op(xc_handle, &op);
+}
+
+
+int xc_vbd_destroy(int xc_handle,
+                   unsigned int domid, 
+                   unsigned short vbdid)
+{
+    block_io_op_t op; 
+    op.cmd = BLOCK_IO_OP_VBD_DELETE; 
+    op.u.delete_params.domain  = domid;
+    op.u.delete_params.vdevice = vbdid;
+    return do_block_io_op(xc_handle, &op);
+}
+
+
+int xc_vbd_add_extent(int xc_handle,
+                      unsigned int domid, 
+                      unsigned short vbdid,
+                      unsigned short real_device,
+                      unsigned long start_sector,
+                      unsigned long nr_sectors)
+{
+    block_io_op_t op; 
+    op.cmd = BLOCK_IO_OP_VBD_ADD; 
+    op.u.add_params.domain  = domid; 
+    op.u.add_params.vdevice = vbdid;
+    op.u.add_params.extent.device       = real_device; 
+    op.u.add_params.extent.start_sector = start_sector;
+    op.u.add_params.extent.nr_sectors   = nr_sectors;
+    return do_block_io_op(xc_handle, &op);
+}
+
+
+int xc_vbd_delete_extent(int xc_handle,
+                         unsigned int domid, 
+                         unsigned short vbdid,
+                         unsigned short real_device,
+                         unsigned long start_sector,
+                         unsigned long nr_sectors)
+{
+    block_io_op_t op; 
+    op.cmd = BLOCK_IO_OP_VBD_REMOVE; 
+    op.u.add_params.domain  = domid; 
+    op.u.add_params.vdevice = vbdid;
+    op.u.add_params.extent.device       = real_device; 
+    op.u.add_params.extent.start_sector = start_sector;
+    op.u.add_params.extent.nr_sectors   = nr_sectors;
+    return do_block_io_op(xc_handle, &op);
+}
+
+
+int xc_vbd_probe(int xc_handle,
+                 unsigned int domid,
+                 unsigned short vbdid,
+                 unsigned int max_vbds,
+                 xc_vbd_t *vbds)
+{
+    block_io_op_t op; 
+    xen_disk_info_t *xdi = &op.u.probe_params.xdi; 
+    int i, j, ret, allocsz = max_vbds * sizeof(xen_disk_t); 
+
+    op.cmd = BLOCK_IO_OP_VBD_PROBE; 
+    op.u.probe_params.domain    = domid; 
+    
+    xdi->max   = max_vbds;
+    xdi->disks = malloc(allocsz);
+    xdi->count = 0;
+
+    if ( (xdi->disks == NULL) || (mlock(xdi->disks, allocsz) != 0) )
+    {
+        if ( xdi->disks != NULL )
+            free(xdi->disks);
+        return -ENOMEM;
+    }
+
+    ret = do_block_io_op(xc_handle, &op);
+
+    (void)munlock(xdi->disks, allocsz);
+
+    if ( ret >= 0 )
+    {
+       for ( i = 0, j = 0; i < xdi->count; i++ )
+        {
+            if ( !(xdi->disks[i].info & XD_FLAG_VIRT) )
+                continue;
+            
+            vbds[j].domid = xdi->disks[i].domain;
+            vbds[j].vbdid = xdi->disks[i].device;
+            vbds[j].flags = (xdi->disks[i].info & XD_FLAG_RO) ? 
+                0 : XC_VBDF_WRITEABLE;
+            vbds[j].nr_sectors = xdi->disks[i].capacity;
+            
+            j++;
+        }
+
+        ret = j;
+    }
+    
+    free(xdi->disks);
+
+    return ret;
+}
diff --git a/tools/xc/lib/libxc_vif.c b/tools/xc/lib/libxc_vif.c
new file mode 100644 (file)
index 0000000..a3e22ea
--- /dev/null
@@ -0,0 +1,69 @@
+/******************************************************************************
+ * libxc_vif.c
+ * 
+ * API for manipulating and accessing per-network-interface parameters.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#include "libxc_private.h"
+
+int xc_vif_scheduler_set(int xc_handle,
+                         unsigned int domid, 
+                         unsigned int vifid, 
+                         xc_vif_sched_params_t *params)
+{
+    network_op_t  netop;
+    netop.cmd = NETWORK_OP_VIFSETPARAMS;
+    netop.u.vif_setparams.domain       = domid;
+    netop.u.vif_setparams.vif          = vifid;
+    netop.u.vif_setparams.credit_bytes = params->credit_bytes;
+    netop.u.vif_setparams.credit_usec  = params->credit_usec;
+    return do_network_op(xc_handle, &netop);
+}
+
+
+int xc_vif_scheduler_get(int xc_handle,
+                         unsigned int domid, 
+                         unsigned int vifid, 
+                         xc_vif_sched_params_t *params)
+{
+    network_op_t  netop;
+    int rc;
+
+    netop.cmd = NETWORK_OP_VIFGETINFO;
+    netop.u.vif_getinfo.domain = domid;
+    netop.u.vif_getinfo.vif    = vifid;
+
+    if ( (rc = do_network_op(xc_handle, &netop)) >= 0 )
+    {
+        params->credit_bytes = netop.u.vif_getinfo.credit_bytes;
+        params->credit_usec  = netop.u.vif_getinfo.credit_usec;
+    }
+
+    return rc;
+}
+
+
+int xc_vif_stats_get(int xc_handle,
+                     unsigned int domid, 
+                     unsigned int vifid, 
+                     xc_vif_stats_t *stats)
+{
+    network_op_t  netop;
+    int rc;
+
+    netop.cmd = NETWORK_OP_VIFGETINFO;
+    netop.u.vif_getinfo.domain = domid;
+    netop.u.vif_getinfo.vif    = vifid;
+
+    if ( (rc = do_network_op(xc_handle, &netop)) >= 0 )
+    {
+        stats->tx_bytes = netop.u.vif_getinfo.total_bytes_sent;
+        stats->tx_pkts  = netop.u.vif_getinfo.total_packets_sent;
+        stats->rx_bytes = netop.u.vif_getinfo.total_bytes_received;
+        stats->rx_pkts  = netop.u.vif_getinfo.total_packets_received;
+    }
+
+    return rc;
+}
diff --git a/tools/xc/lib/rpm.spec b/tools/xc/lib/rpm.spec
new file mode 100644 (file)
index 0000000..1b4c5fc
--- /dev/null
@@ -0,0 +1,28 @@
+Summary: Xen control interface library
+Name: xen-internal-library
+Version: 1.2
+Release: 1
+License: Xen
+Group: Xen
+BuildRoot: %{staging}
+%description
+Library to make it easier to access the Xen control interfaces.
+
+%pre
+%preun
+%install
+install -m 0755 -d $RPM_BUILD_ROOT/lib
+install -m 0755 libxc.a $RPM_BUILD_ROOT/lib/libxc.a
+install -m 0755 libxc.so $RPM_BUILD_ROOT/lib/libxc.so
+install -m 0755 -d $RPM_BUILD_ROOT/include
+install -m 0644 xc.h $RPM_BUILD_ROOT/include/xc.h
+%clean
+%post
+%postun
+%files
+%defattr(-,root,root)
+%dir /lib
+/lib/libxc.a
+/lib/libxc.so
+%dir /include
+/include/xc.h
diff --git a/tools/xc/lib/xc.h b/tools/xc/lib/xc.h
new file mode 100644 (file)
index 0000000..ec8c483
--- /dev/null
@@ -0,0 +1,127 @@
+/******************************************************************************
+ * xc.h
+ * 
+ * A library for low-level access to the Xen control interfaces.
+ * 
+ * Copyright (c) 2003, K A Fraser.
+ */
+
+#ifndef __XC_H__
+#define __XC_H__
+
+/* Obtain or relinquish a handle on the 'xc' library. */
+int xc_interface_open(void);
+int xc_interface_close(int xc_handle);
+
+typedef struct {
+    unsigned int  domid;
+    unsigned int  cpu;
+    int           has_cpu;
+    int           stopped;
+    unsigned long nr_pages;
+    unsigned long long cpu_time;
+#define XC_DOMINFO_MAXNAME 16
+    char          name[XC_DOMINFO_MAXNAME];
+} xc_dominfo_t;
+
+int xc_domain_create(int xc_handle, 
+                     unsigned int mem_kb, 
+                     const char *name);
+int xc_domain_start(int xc_handle, 
+                    unsigned int domid);
+int xc_domain_stop(int xc_handle, 
+                   unsigned int domid);
+int xc_domain_destroy(int xc_handle, 
+                      unsigned int domid, 
+                      int force);
+int xc_domain_getinfo(int xc_handle,
+                      unsigned int first_domid, 
+                      unsigned int max_doms,
+                      xc_dominfo_t *info);
+
+int xc_linux_save(int xc_handle,
+                  unsigned int domid, 
+                  const char *state_file, 
+                  int verbose);
+int xc_linux_restore(int xc_handle,
+                     const char *state_file, int verbose);
+int xc_linux_build(int xc_handle,
+                   unsigned int domid,
+                   const char *image_name,
+                   const char *ramdisk_name,
+                   const char *cmdline);
+
+int xc_bvtsched_global_set(int xc_handle,
+                           unsigned long ctx_allow);
+int xc_bvtsched_domain_set(int xc_handle,
+                           unsigned int domid,
+                           unsigned long mcuadv,
+                           unsigned long warp,
+                           unsigned long warpl,
+                           unsigned long warpu);
+
+typedef struct {
+    unsigned long credit_bytes;
+    unsigned long credit_usec;
+} xc_vif_sched_params_t;
+
+typedef struct {
+    unsigned long long tx_bytes, tx_pkts;
+    unsigned long long rx_bytes, rx_pkts;
+} xc_vif_stats_t;
+
+int xc_vif_scheduler_set(int xc_handle,
+                         unsigned int domid, 
+                         unsigned int vifid,
+                         xc_vif_sched_params_t *params);
+int xc_vif_scheduler_get(int xc_handle,
+                         unsigned int domid, 
+                         unsigned int vifid,
+                         xc_vif_sched_params_t *params);
+int xc_vif_stats_get(int xc_handle,
+                     unsigned int domid, 
+                     unsigned int vifid,
+                     xc_vif_stats_t *stats);
+
+typedef struct {
+#define XC_VBDDOM_PROBE_ALL (~0U)
+    unsigned int   domid;
+    unsigned short vbdid;
+#define XC_VBDF_WRITEABLE (1<<0)
+    unsigned long  flags;
+    unsigned long  nr_sectors;
+} xc_vbd_t;
+
+
+int xc_vbd_create(int xc_handle,
+                  unsigned int domid, 
+                  unsigned short vbdid, 
+                  int writeable);
+int xc_vbd_destroy(int xc_handle,
+                   unsigned int domid, 
+                   unsigned short vbdid);
+int xc_vbd_add_extent(int xc_handle,
+                      unsigned int domid, 
+                      unsigned short vbdid,
+                      unsigned short real_device,
+                      unsigned long start_sector,
+                      unsigned long nr_sectors);
+int xc_vbd_delete_extent(int xc_handle,
+                         unsigned int domid, 
+                         unsigned short vbdid,
+                         unsigned short real_device,
+                         unsigned long start_sector,
+                         unsigned long nr_sectors);
+int xc_vbd_probe(int xc_handle,
+                 unsigned int domid,
+                 unsigned short vbdid,
+                 unsigned int max_vbds,
+                 xc_vbd_t *vbds);
+
+int xc_readconsolering(int xc_handle,
+                       char *str, 
+                       unsigned int max_chars, 
+                       int clear);
+
+
+#endif /* __XC_H__ */